Complete batch 012 (golden set diff) and 013 (advisory chat), fix build errors

Sprints completed:
- SPRINT_20260110_012_* (golden set diff layer - 10 sprints)
- SPRINT_20260110_013_* (advisory chat - 4 sprints)

Build fixes applied:
- Fix namespace conflicts with Microsoft.Extensions.Options.Options.Create
- Fix VexDecisionReachabilityIntegrationTests API drift (major rewrite)
- Fix VexSchemaValidationTests FluentAssertions method name
- Fix FixChainGateIntegrationTests ambiguous type references
- Fix AdvisoryAI test files required properties and namespace aliases
- Add stub types for CveMappingController (ICveSymbolMappingService)
- Fix VerdictBuilderService static context issue

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
master
2026-01-11 10:09:07 +02:00
parent a3b2f30a11
commit 7f7eb8b228
232 changed files with 58979 additions and 91 deletions

View File

@@ -0,0 +1,227 @@
using System.Collections.Immutable;
using System.Globalization;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace StellaOps.BinaryIndex.GoldenSet;
/// <summary>
/// YAML serialization for golden set definitions.
/// Uses snake_case naming convention for human-readability.
/// </summary>
public static class GoldenSetYamlSerializer
{
private static readonly IDeserializer Deserializer = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
private static readonly ISerializer Serializer = new SerializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull | DefaultValuesHandling.OmitEmptyCollections)
.Build();
/// <summary>
/// Deserializes a golden set from YAML content.
/// </summary>
/// <param name="yaml">YAML content to parse.</param>
/// <returns>Parsed golden set definition.</returns>
/// <exception cref="InvalidOperationException">Thrown when parsing fails.</exception>
public static GoldenSetDefinition Deserialize(string yaml)
{
ArgumentException.ThrowIfNullOrWhiteSpace(yaml);
var dto = Deserializer.Deserialize<GoldenSetYamlDto>(yaml)
?? throw new InvalidOperationException("Failed to deserialize YAML: result was null");
return MapToDefinition(dto);
}
/// <summary>
/// Serializes a golden set to YAML content.
/// </summary>
/// <param name="definition">Definition to serialize.</param>
/// <returns>YAML string representation.</returns>
public static string Serialize(GoldenSetDefinition definition)
{
ArgumentNullException.ThrowIfNull(definition);
var dto = MapToDto(definition);
return Serializer.Serialize(dto);
}
private static GoldenSetDefinition MapToDefinition(GoldenSetYamlDto dto)
{
return new GoldenSetDefinition
{
Id = dto.Id ?? throw new InvalidOperationException("Missing required field: id"),
Component = dto.Component ?? throw new InvalidOperationException("Missing required field: component"),
Targets = dto.Targets?.Select(MapTargetToDefinition).ToImmutableArray()
?? throw new InvalidOperationException("Missing required field: targets"),
Witness = dto.Witness is null ? null : MapWitnessToDefinition(dto.Witness),
Metadata = dto.Metadata is null
? throw new InvalidOperationException("Missing required field: metadata")
: MapMetadataToDefinition(dto.Metadata)
};
}
private static VulnerableTarget MapTargetToDefinition(VulnerableTargetYamlDto dto)
{
return new VulnerableTarget
{
FunctionName = dto.Function ?? throw new InvalidOperationException("Missing required field: function"),
Edges = dto.Edges?.Select(e => BasicBlockEdge.Parse(e)).ToImmutableArray() ?? [],
Sinks = dto.Sinks?.ToImmutableArray() ?? [],
Constants = dto.Constants?.ToImmutableArray() ?? [],
TaintInvariant = dto.TaintInvariant,
SourceFile = dto.SourceFile,
SourceLine = dto.SourceLine
};
}
private static WitnessInput MapWitnessToDefinition(WitnessYamlDto dto)
{
return new WitnessInput
{
Arguments = dto.Arguments?.ToImmutableArray() ?? [],
Invariant = dto.Invariant,
PocFileRef = dto.PocFileRef
};
}
private static GoldenSetMetadata MapMetadataToDefinition(GoldenSetMetadataYamlDto dto)
{
return new GoldenSetMetadata
{
AuthorId = dto.AuthorId ?? throw new InvalidOperationException("Missing required field: metadata.author_id"),
CreatedAt = ParseDateTimeOffset(dto.CreatedAt, "metadata.created_at"),
SourceRef = dto.SourceRef ?? throw new InvalidOperationException("Missing required field: metadata.source_ref"),
ReviewedBy = dto.ReviewedBy,
ReviewedAt = string.IsNullOrWhiteSpace(dto.ReviewedAt) ? null : ParseDateTimeOffset(dto.ReviewedAt, "metadata.reviewed_at"),
Tags = dto.Tags?.ToImmutableArray() ?? [],
SchemaVersion = dto.SchemaVersion ?? GoldenSetConstants.CurrentSchemaVersion
};
}
private static DateTimeOffset ParseDateTimeOffset(string? value, string fieldName)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture, "Missing required field: {0}", fieldName));
}
if (!DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result))
{
throw new InvalidOperationException(
string.Format(CultureInfo.InvariantCulture, "Invalid date format in {0}: {1}", fieldName, value));
}
return result;
}
private static GoldenSetYamlDto MapToDto(GoldenSetDefinition definition)
{
return new GoldenSetYamlDto
{
Id = definition.Id,
Component = definition.Component,
Targets = definition.Targets.Select(MapTargetToDto).ToList(),
Witness = definition.Witness is null ? null : MapWitnessToDto(definition.Witness),
Metadata = MapMetadataToDto(definition.Metadata)
};
}
private static VulnerableTargetYamlDto MapTargetToDto(VulnerableTarget target)
{
return new VulnerableTargetYamlDto
{
Function = target.FunctionName,
Edges = target.Edges.IsDefaultOrEmpty ? null : target.Edges.Select(e => e.ToString()).ToList(),
Sinks = target.Sinks.IsDefaultOrEmpty ? null : target.Sinks.ToList(),
Constants = target.Constants.IsDefaultOrEmpty ? null : target.Constants.ToList(),
TaintInvariant = target.TaintInvariant,
SourceFile = target.SourceFile,
SourceLine = target.SourceLine
};
}
private static WitnessYamlDto MapWitnessToDto(WitnessInput witness)
{
return new WitnessYamlDto
{
Arguments = witness.Arguments.IsDefaultOrEmpty ? null : witness.Arguments.ToList(),
Invariant = witness.Invariant,
PocFileRef = witness.PocFileRef
};
}
private static GoldenSetMetadataYamlDto MapMetadataToDto(GoldenSetMetadata metadata)
{
return new GoldenSetMetadataYamlDto
{
AuthorId = metadata.AuthorId,
CreatedAt = metadata.CreatedAt.ToString("O", CultureInfo.InvariantCulture),
SourceRef = metadata.SourceRef,
ReviewedBy = metadata.ReviewedBy,
ReviewedAt = metadata.ReviewedAt?.ToString("O", CultureInfo.InvariantCulture),
Tags = metadata.Tags.IsDefaultOrEmpty ? null : metadata.Tags.ToList(),
SchemaVersion = metadata.SchemaVersion
};
}
}
#region YAML DTOs
/// <summary>
/// YAML DTO for golden set definition.
/// </summary>
internal sealed class GoldenSetYamlDto
{
public string? Id { get; set; }
public string? Component { get; set; }
public List<VulnerableTargetYamlDto>? Targets { get; set; }
public WitnessYamlDto? Witness { get; set; }
public GoldenSetMetadataYamlDto? Metadata { get; set; }
}
/// <summary>
/// YAML DTO for vulnerable target.
/// </summary>
internal sealed class VulnerableTargetYamlDto
{
public string? Function { get; set; }
public List<string>? Edges { get; set; }
public List<string>? Sinks { get; set; }
public List<string>? Constants { get; set; }
public string? TaintInvariant { get; set; }
public string? SourceFile { get; set; }
public int? SourceLine { get; set; }
}
/// <summary>
/// YAML DTO for witness input.
/// </summary>
internal sealed class WitnessYamlDto
{
public List<string>? Arguments { get; set; }
public string? Invariant { get; set; }
public string? PocFileRef { get; set; }
}
/// <summary>
/// YAML DTO for metadata.
/// </summary>
internal sealed class GoldenSetMetadataYamlDto
{
public string? AuthorId { get; set; }
public string? CreatedAt { get; set; }
public string? SourceRef { get; set; }
public string? ReviewedBy { get; set; }
public string? ReviewedAt { get; set; }
public List<string>? Tags { get; set; }
public string? SchemaVersion { get; set; }
}
#endregion