finish off sprint advisories and sprints
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// Copyright (c) 2025 StellaOps
|
||||
// Sprint: SPRINT_20260122_039_Scanner_runtime_linkage_verification
|
||||
// Task: RLV-009 - Platform API: Function Map Endpoints
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Request for creating a function map.
|
||||
/// </summary>
|
||||
public sealed record CreateFunctionMapRequest
|
||||
{
|
||||
[JsonPropertyName("sbomRef")]
|
||||
public required string SbomRef { get; init; }
|
||||
|
||||
[JsonPropertyName("serviceName")]
|
||||
public required string ServiceName { get; init; }
|
||||
|
||||
[JsonPropertyName("hotFunctions")]
|
||||
public IReadOnlyList<string>? HotFunctions { get; init; }
|
||||
|
||||
[JsonPropertyName("options")]
|
||||
public FunctionMapOptionsDto? Options { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options for function map generation.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapOptionsDto
|
||||
{
|
||||
[JsonPropertyName("minObservationRate")]
|
||||
public double? MinObservationRate { get; init; }
|
||||
|
||||
[JsonPropertyName("windowSeconds")]
|
||||
public int? WindowSeconds { get; init; }
|
||||
|
||||
[JsonPropertyName("failOnUnexpected")]
|
||||
public bool? FailOnUnexpected { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request for verifying observations against a function map.
|
||||
/// </summary>
|
||||
public sealed record VerifyFunctionMapRequest
|
||||
{
|
||||
[JsonPropertyName("observations")]
|
||||
public IReadOnlyList<ObservationDto>? Observations { get; init; }
|
||||
|
||||
[JsonPropertyName("options")]
|
||||
public VerifyOptionsDto? Options { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Observation DTO for API requests.
|
||||
/// </summary>
|
||||
public sealed record ObservationDto
|
||||
{
|
||||
[JsonPropertyName("observation_id")]
|
||||
public required string ObservationId { get; init; }
|
||||
|
||||
[JsonPropertyName("node_hash")]
|
||||
public required string NodeHash { get; init; }
|
||||
|
||||
[JsonPropertyName("function_name")]
|
||||
public required string FunctionName { get; init; }
|
||||
|
||||
[JsonPropertyName("probe_type")]
|
||||
public required string ProbeType { get; init; }
|
||||
|
||||
[JsonPropertyName("observed_at")]
|
||||
public required DateTimeOffset ObservedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("observation_count")]
|
||||
public int ObservationCount { get; init; } = 1;
|
||||
|
||||
[JsonPropertyName("container_id")]
|
||||
public string? ContainerId { get; init; }
|
||||
|
||||
[JsonPropertyName("pod_name")]
|
||||
public string? PodName { get; init; }
|
||||
|
||||
[JsonPropertyName("namespace")]
|
||||
public string? Namespace { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification options DTO.
|
||||
/// </summary>
|
||||
public sealed record VerifyOptionsDto
|
||||
{
|
||||
[JsonPropertyName("minObservationRateOverride")]
|
||||
public double? MinObservationRateOverride { get; init; }
|
||||
|
||||
[JsonPropertyName("windowSecondsOverride")]
|
||||
public int? WindowSecondsOverride { get; init; }
|
||||
|
||||
[JsonPropertyName("failOnUnexpectedOverride")]
|
||||
public bool? FailOnUnexpectedOverride { get; init; }
|
||||
|
||||
[JsonPropertyName("containerIdFilter")]
|
||||
public string? ContainerIdFilter { get; init; }
|
||||
|
||||
[JsonPropertyName("podNameFilter")]
|
||||
public string? PodNameFilter { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function map summary returned in list responses.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapSummary
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public required string Id { get; init; }
|
||||
|
||||
[JsonPropertyName("serviceName")]
|
||||
public required string ServiceName { get; init; }
|
||||
|
||||
[JsonPropertyName("sbomRef")]
|
||||
public required string SbomRef { get; init; }
|
||||
|
||||
[JsonPropertyName("pathCount")]
|
||||
public required int PathCount { get; init; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("lastVerifiedAt")]
|
||||
public DateTimeOffset? LastVerifiedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("coverageStatus")]
|
||||
public string? CoverageStatus { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full function map detail returned in get responses.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapDetail
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public required string Id { get; init; }
|
||||
|
||||
[JsonPropertyName("serviceName")]
|
||||
public required string ServiceName { get; init; }
|
||||
|
||||
[JsonPropertyName("sbomRef")]
|
||||
public required string SbomRef { get; init; }
|
||||
|
||||
[JsonPropertyName("pathCount")]
|
||||
public required int PathCount { get; init; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("lastVerifiedAt")]
|
||||
public DateTimeOffset? LastVerifiedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("coverage")]
|
||||
public FunctionMapCoverageDto? Coverage { get; init; }
|
||||
|
||||
[JsonPropertyName("predicateDigest")]
|
||||
public required string PredicateDigest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coverage thresholds and current status.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapCoverageDto
|
||||
{
|
||||
[JsonPropertyName("minObservationRate")]
|
||||
public required double MinObservationRate { get; init; }
|
||||
|
||||
[JsonPropertyName("windowSeconds")]
|
||||
public required int WindowSeconds { get; init; }
|
||||
|
||||
[JsonPropertyName("failOnUnexpected")]
|
||||
public required bool FailOnUnexpected { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification result returned from verify endpoint.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapVerifyResponse
|
||||
{
|
||||
[JsonPropertyName("verified")]
|
||||
public required bool Verified { get; init; }
|
||||
|
||||
[JsonPropertyName("observationRate")]
|
||||
public required double ObservationRate { get; init; }
|
||||
|
||||
[JsonPropertyName("targetRate")]
|
||||
public required double TargetRate { get; init; }
|
||||
|
||||
[JsonPropertyName("pathCount")]
|
||||
public required int PathCount { get; init; }
|
||||
|
||||
[JsonPropertyName("observedPaths")]
|
||||
public required int ObservedPaths { get; init; }
|
||||
|
||||
[JsonPropertyName("unexpectedSymbolCount")]
|
||||
public required int UnexpectedSymbolCount { get; init; }
|
||||
|
||||
[JsonPropertyName("missingSymbolCount")]
|
||||
public required int MissingSymbolCount { get; init; }
|
||||
|
||||
[JsonPropertyName("verifiedAt")]
|
||||
public required DateTimeOffset VerifiedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("evidenceDigest")]
|
||||
public required string EvidenceDigest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coverage statistics response.
|
||||
/// </summary>
|
||||
public sealed record FunctionMapCoverageResponse
|
||||
{
|
||||
[JsonPropertyName("totalPaths")]
|
||||
public required int TotalPaths { get; init; }
|
||||
|
||||
[JsonPropertyName("observedPaths")]
|
||||
public required int ObservedPaths { get; init; }
|
||||
|
||||
[JsonPropertyName("totalExpectedCalls")]
|
||||
public required int TotalExpectedCalls { get; init; }
|
||||
|
||||
[JsonPropertyName("observedCalls")]
|
||||
public required int ObservedCalls { get; init; }
|
||||
|
||||
[JsonPropertyName("coverageRate")]
|
||||
public required double CoverageRate { get; init; }
|
||||
|
||||
[JsonPropertyName("unexpectedSymbolCount")]
|
||||
public required int UnexpectedSymbolCount { get; init; }
|
||||
|
||||
[JsonPropertyName("asOf")]
|
||||
public required DateTimeOffset AsOf { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// Copyright (c) 2025 StellaOps
|
||||
// Sprint: SPRINT_20260122_041_Policy_interop_import_export_rego
|
||||
// Task: TASK-07 - Platform API Endpoints
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Request to export a policy to a specified format.
|
||||
/// </summary>
|
||||
public sealed record PolicyExportApiRequest
|
||||
{
|
||||
[JsonPropertyName("policy_content")]
|
||||
public string? PolicyContent { get; init; }
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public string Format { get; init; } = "json";
|
||||
|
||||
[JsonPropertyName("environment")]
|
||||
public string? Environment { get; init; }
|
||||
|
||||
[JsonPropertyName("include_remediation")]
|
||||
public bool IncludeRemediation { get; init; } = true;
|
||||
|
||||
[JsonPropertyName("include_comments")]
|
||||
public bool IncludeComments { get; init; } = true;
|
||||
|
||||
[JsonPropertyName("package_name")]
|
||||
public string? PackageName { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from a policy export operation.
|
||||
/// </summary>
|
||||
public sealed record PolicyExportApiResponse
|
||||
{
|
||||
[JsonPropertyName("success")]
|
||||
public bool Success { get; init; }
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public string Format { get; init; } = "json";
|
||||
|
||||
[JsonPropertyName("content")]
|
||||
public string? Content { get; init; }
|
||||
|
||||
[JsonPropertyName("digest")]
|
||||
public string? Digest { get; init; }
|
||||
|
||||
[JsonPropertyName("diagnostics")]
|
||||
public IReadOnlyList<PolicyInteropDiagnostic>? Diagnostics { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request to import a policy from a specified format.
|
||||
/// </summary>
|
||||
public sealed record PolicyImportApiRequest
|
||||
{
|
||||
[JsonPropertyName("content")]
|
||||
public string Content { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public string? Format { get; init; }
|
||||
|
||||
[JsonPropertyName("validate_only")]
|
||||
public bool ValidateOnly { get; init; }
|
||||
|
||||
[JsonPropertyName("merge_strategy")]
|
||||
public string MergeStrategy { get; init; } = "replace";
|
||||
|
||||
[JsonPropertyName("dry_run")]
|
||||
public bool DryRun { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from a policy import operation.
|
||||
/// </summary>
|
||||
public sealed record PolicyImportApiResponse
|
||||
{
|
||||
[JsonPropertyName("success")]
|
||||
public bool Success { get; init; }
|
||||
|
||||
[JsonPropertyName("source_format")]
|
||||
public string? SourceFormat { get; init; }
|
||||
|
||||
[JsonPropertyName("gates_imported")]
|
||||
public int GatesImported { get; init; }
|
||||
|
||||
[JsonPropertyName("rules_imported")]
|
||||
public int RulesImported { get; init; }
|
||||
|
||||
[JsonPropertyName("native_mapped")]
|
||||
public int NativeMapped { get; init; }
|
||||
|
||||
[JsonPropertyName("opa_evaluated")]
|
||||
public int OpaEvaluated { get; init; }
|
||||
|
||||
[JsonPropertyName("diagnostics")]
|
||||
public IReadOnlyList<PolicyInteropDiagnostic>? Diagnostics { get; init; }
|
||||
|
||||
[JsonPropertyName("mappings")]
|
||||
public IReadOnlyList<PolicyImportMappingDto>? Mappings { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request to validate a policy document.
|
||||
/// </summary>
|
||||
public sealed record PolicyValidateApiRequest
|
||||
{
|
||||
[JsonPropertyName("content")]
|
||||
public string Content { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public string? Format { get; init; }
|
||||
|
||||
[JsonPropertyName("strict")]
|
||||
public bool Strict { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from a policy validation operation.
|
||||
/// </summary>
|
||||
public sealed record PolicyValidateApiResponse
|
||||
{
|
||||
[JsonPropertyName("valid")]
|
||||
public bool Valid { get; init; }
|
||||
|
||||
[JsonPropertyName("detected_format")]
|
||||
public string? DetectedFormat { get; init; }
|
||||
|
||||
[JsonPropertyName("errors")]
|
||||
public IReadOnlyList<PolicyInteropDiagnostic>? Errors { get; init; }
|
||||
|
||||
[JsonPropertyName("warnings")]
|
||||
public IReadOnlyList<PolicyInteropDiagnostic>? Warnings { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request to evaluate a policy against evidence input.
|
||||
/// </summary>
|
||||
public sealed record PolicyEvaluateApiRequest
|
||||
{
|
||||
[JsonPropertyName("policy_content")]
|
||||
public string PolicyContent { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("input")]
|
||||
public PolicyEvaluationInputDto? Input { get; init; }
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public string? Format { get; init; }
|
||||
|
||||
[JsonPropertyName("environment")]
|
||||
public string? Environment { get; init; }
|
||||
|
||||
[JsonPropertyName("include_remediation")]
|
||||
public bool IncludeRemediation { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from a policy evaluation operation.
|
||||
/// </summary>
|
||||
public sealed record PolicyEvaluateApiResponse
|
||||
{
|
||||
[JsonPropertyName("decision")]
|
||||
public string Decision { get; init; } = "block";
|
||||
|
||||
[JsonPropertyName("gates")]
|
||||
public IReadOnlyList<GateEvaluationDto>? Gates { get; init; }
|
||||
|
||||
[JsonPropertyName("remediation")]
|
||||
public IReadOnlyList<RemediationHintDto>? Remediation { get; init; }
|
||||
|
||||
[JsonPropertyName("output_digest")]
|
||||
public string? OutputDigest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simplified evidence input for API evaluation.
|
||||
/// </summary>
|
||||
public sealed record PolicyEvaluationInputDto
|
||||
{
|
||||
[JsonPropertyName("environment")]
|
||||
public string? Environment { get; init; }
|
||||
|
||||
[JsonPropertyName("dsse_verified")]
|
||||
public bool? DsseVerified { get; init; }
|
||||
|
||||
[JsonPropertyName("rekor_verified")]
|
||||
public bool? RekorVerified { get; init; }
|
||||
|
||||
[JsonPropertyName("sbom_digest")]
|
||||
public string? SbomDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("freshness_verified")]
|
||||
public bool? FreshnessVerified { get; init; }
|
||||
|
||||
[JsonPropertyName("cvss_score")]
|
||||
public double? CvssScore { get; init; }
|
||||
|
||||
[JsonPropertyName("confidence")]
|
||||
public double? Confidence { get; init; }
|
||||
|
||||
[JsonPropertyName("reachability_status")]
|
||||
public string? ReachabilityStatus { get; init; }
|
||||
|
||||
[JsonPropertyName("unknowns_ratio")]
|
||||
public double? UnknownsRatio { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gate evaluation result DTO.
|
||||
/// </summary>
|
||||
public sealed record GateEvaluationDto
|
||||
{
|
||||
[JsonPropertyName("gate_id")]
|
||||
public string GateId { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("gate_type")]
|
||||
public string GateType { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("passed")]
|
||||
public bool Passed { get; init; }
|
||||
|
||||
[JsonPropertyName("reason")]
|
||||
public string? Reason { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remediation hint DTO for API responses.
|
||||
/// </summary>
|
||||
public sealed record RemediationHintDto
|
||||
{
|
||||
[JsonPropertyName("code")]
|
||||
public string Code { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("severity")]
|
||||
public string Severity { get; init; } = "medium";
|
||||
|
||||
[JsonPropertyName("actions")]
|
||||
public IReadOnlyList<RemediationActionDto>? Actions { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remediation action DTO.
|
||||
/// </summary>
|
||||
public sealed record RemediationActionDto
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("command")]
|
||||
public string? Command { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import mapping showing how Rego rules were translated.
|
||||
/// </summary>
|
||||
public sealed record PolicyImportMappingDto
|
||||
{
|
||||
[JsonPropertyName("source_rule")]
|
||||
public string SourceRule { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("target_gate_type")]
|
||||
public string TargetGateType { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("mapped_to_native")]
|
||||
public bool MappedToNative { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diagnostic message from interop operations.
|
||||
/// </summary>
|
||||
public sealed record PolicyInteropDiagnostic
|
||||
{
|
||||
[JsonPropertyName("severity")]
|
||||
public string Severity { get; init; } = "info";
|
||||
|
||||
[JsonPropertyName("code")]
|
||||
public string Code { get; init; } = "";
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string Message { get; init; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response listing supported formats.
|
||||
/// </summary>
|
||||
public sealed record PolicyFormatsApiResponse
|
||||
{
|
||||
[JsonPropertyName("formats")]
|
||||
public IReadOnlyList<PolicyFormatInfo> Formats { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about a supported policy format.
|
||||
/// </summary>
|
||||
public sealed record PolicyFormatInfo(
|
||||
[property: JsonPropertyName("id")] string Id,
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("schema")] string Schema,
|
||||
[property: JsonPropertyName("import_supported")] bool ImportSupported,
|
||||
[property: JsonPropertyName("export_supported")] bool ExportSupported);
|
||||
@@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// Copyright (c) 2025 StellaOps
|
||||
// Sprint: SPRINT_20260122_037_Signals_unified_trust_score_algebra
|
||||
// Task: Score persistence store
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Record representing a persisted score history entry.
|
||||
/// </summary>
|
||||
public sealed record ScoreHistoryRecord
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public required string Id { get; init; }
|
||||
|
||||
[JsonPropertyName("tenant_id")]
|
||||
public required string TenantId { get; init; }
|
||||
|
||||
[JsonPropertyName("project_id")]
|
||||
public required string ProjectId { get; init; }
|
||||
|
||||
[JsonPropertyName("cve_id")]
|
||||
public required string CveId { get; init; }
|
||||
|
||||
[JsonPropertyName("purl")]
|
||||
public string? Purl { get; init; }
|
||||
|
||||
[JsonPropertyName("score")]
|
||||
public required decimal Score { get; init; }
|
||||
|
||||
[JsonPropertyName("band")]
|
||||
public required string Band { get; init; }
|
||||
|
||||
[JsonPropertyName("weights_version")]
|
||||
public required string WeightsVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("signal_snapshot")]
|
||||
public required string SignalSnapshot { get; init; }
|
||||
|
||||
[JsonPropertyName("replay_digest")]
|
||||
public required string ReplayDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("created_at")]
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,670 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// Copyright (c) 2025 StellaOps
|
||||
// Sprint: SPRINT_20260122_037_Signals_unified_trust_score_algebra
|
||||
// Task: TSF-005 - Platform API Endpoints (Score Evaluate)
|
||||
// Task: TSF-011 - Score Replay & Verification Endpoint
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Request for score evaluation.
|
||||
/// </summary>
|
||||
public sealed record ScoreEvaluateRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// SBOM reference (OCI digest or URL).
|
||||
/// </summary>
|
||||
[JsonPropertyName("sbom_ref")]
|
||||
public string? SbomRef { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// CVE identifier for direct scoring.
|
||||
/// </summary>
|
||||
[JsonPropertyName("cve_id")]
|
||||
public string? CveId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package URL (purl) for component identification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("purl")]
|
||||
public string? Purl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// CVSS vector string (e.g., "CVSS:3.1/AV:N/AC:L/...").
|
||||
/// </summary>
|
||||
[JsonPropertyName("cvss_vector")]
|
||||
public string? CvssVector { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// VEX document references.
|
||||
/// </summary>
|
||||
[JsonPropertyName("vex_refs")]
|
||||
public IReadOnlyList<string>? VexRefs { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Rekor receipt data for attestation verification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("rekor_receipts")]
|
||||
public IReadOnlyList<string>? RekorReceipts { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Runtime witness observations.
|
||||
/// </summary>
|
||||
[JsonPropertyName("runtime_witnesses")]
|
||||
public IReadOnlyList<RuntimeWitnessInput>? RuntimeWitnesses { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Signal inputs for direct scoring.
|
||||
/// </summary>
|
||||
[JsonPropertyName("signals")]
|
||||
public SignalInputs? Signals { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scoring options.
|
||||
/// </summary>
|
||||
[JsonPropertyName("options")]
|
||||
public ScoreEvaluateOptions? Options { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runtime witness input.
|
||||
/// </summary>
|
||||
public sealed record RuntimeWitnessInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Witness type (process, network, file, etc.).
|
||||
/// </summary>
|
||||
[JsonPropertyName("type")]
|
||||
public required string Type { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Witness data.
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public required string Data { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the witness was observed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("observed_at")]
|
||||
public DateTimeOffset? ObservedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Direct signal inputs for scoring.
|
||||
/// </summary>
|
||||
public sealed record SignalInputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Reachability signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("reachability")]
|
||||
public double? Reachability { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Runtime signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("runtime")]
|
||||
public double? Runtime { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Backport signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("backport")]
|
||||
public double? Backport { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Exploit signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("exploit")]
|
||||
public double? Exploit { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Source signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("source")]
|
||||
public double? Source { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Mitigation signal (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("mitigation")]
|
||||
public double? Mitigation { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Score evaluation options.
|
||||
/// </summary>
|
||||
public sealed record ScoreEvaluateOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Decay lambda for time-based decay.
|
||||
/// </summary>
|
||||
[JsonPropertyName("decay_lambda")]
|
||||
public double? DecayLambda { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Weight set ID (manifest version) to use.
|
||||
/// </summary>
|
||||
[JsonPropertyName("weight_set_id")]
|
||||
public string? WeightSetId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Include delta-if-present calculations.
|
||||
/// </summary>
|
||||
[JsonPropertyName("include_delta")]
|
||||
public bool IncludeDelta { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Include detailed breakdown.
|
||||
/// </summary>
|
||||
[JsonPropertyName("include_breakdown")]
|
||||
public bool IncludeBreakdown { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from score evaluation.
|
||||
/// </summary>
|
||||
public sealed record ScoreEvaluateResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique score ID for replay lookup.
|
||||
/// </summary>
|
||||
[JsonPropertyName("score_id")]
|
||||
public required string ScoreId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Score value (0-100).
|
||||
/// </summary>
|
||||
[JsonPropertyName("score_value")]
|
||||
public required int ScoreValue { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Score bucket (ActNow, ScheduleNext, Investigate, Watchlist).
|
||||
/// </summary>
|
||||
[JsonPropertyName("bucket")]
|
||||
public required string Bucket { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknowns fraction (U) from entropy (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("unknowns_fraction")]
|
||||
public double? UnknownsFraction { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknowns band (Complete, Adequate, Sparse, Insufficient).
|
||||
/// </summary>
|
||||
[JsonPropertyName("unknowns_band")]
|
||||
public string? UnknownsBand { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Unknown package references.
|
||||
/// </summary>
|
||||
[JsonPropertyName("unknowns")]
|
||||
public IReadOnlyList<string>? Unknowns { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// OCI reference to score proof bundle.
|
||||
/// </summary>
|
||||
[JsonPropertyName("proof_ref")]
|
||||
public string? ProofRef { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Dimension breakdown.
|
||||
/// </summary>
|
||||
[JsonPropertyName("breakdown")]
|
||||
public IReadOnlyList<DimensionBreakdown>? Breakdown { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Applied guardrails.
|
||||
/// </summary>
|
||||
[JsonPropertyName("guardrails")]
|
||||
public GuardrailsApplied? Guardrails { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Delta-if-present calculations.
|
||||
/// </summary>
|
||||
[JsonPropertyName("delta_if_present")]
|
||||
public IReadOnlyList<SignalDeltaResponse>? DeltaIfPresent { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Detected conflicts.
|
||||
/// </summary>
|
||||
[JsonPropertyName("conflicts")]
|
||||
public IReadOnlyList<SignalConflictResponse>? Conflicts { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Weight manifest reference.
|
||||
/// </summary>
|
||||
[JsonPropertyName("weight_manifest")]
|
||||
public WeightManifestReference? WeightManifest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// EWS digest for replay.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ews_digest")]
|
||||
public required string EwsDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Determinization fingerprint for replay.
|
||||
/// </summary>
|
||||
[JsonPropertyName("determinization_fingerprint")]
|
||||
public string? DeterminizationFingerprint { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the score was computed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("computed_at")]
|
||||
public required DateTimeOffset ComputedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dimension breakdown in response.
|
||||
/// </summary>
|
||||
public sealed record DimensionBreakdown
|
||||
{
|
||||
[JsonPropertyName("dimension")]
|
||||
public required string Dimension { get; init; }
|
||||
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
[JsonPropertyName("input_value")]
|
||||
public required double InputValue { get; init; }
|
||||
|
||||
[JsonPropertyName("weight")]
|
||||
public required double Weight { get; init; }
|
||||
|
||||
[JsonPropertyName("contribution")]
|
||||
public required double Contribution { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Guardrails applied in scoring.
|
||||
/// </summary>
|
||||
public sealed record GuardrailsApplied
|
||||
{
|
||||
[JsonPropertyName("speculative_cap")]
|
||||
public bool SpeculativeCap { get; init; }
|
||||
|
||||
[JsonPropertyName("not_affected_cap")]
|
||||
public bool NotAffectedCap { get; init; }
|
||||
|
||||
[JsonPropertyName("runtime_floor")]
|
||||
public bool RuntimeFloor { get; init; }
|
||||
|
||||
[JsonPropertyName("original_score")]
|
||||
public int OriginalScore { get; init; }
|
||||
|
||||
[JsonPropertyName("adjusted_score")]
|
||||
public int AdjustedScore { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal delta response.
|
||||
/// </summary>
|
||||
public sealed record SignalDeltaResponse
|
||||
{
|
||||
[JsonPropertyName("signal")]
|
||||
public required string Signal { get; init; }
|
||||
|
||||
[JsonPropertyName("min_impact")]
|
||||
public required double MinImpact { get; init; }
|
||||
|
||||
[JsonPropertyName("max_impact")]
|
||||
public required double MaxImpact { get; init; }
|
||||
|
||||
[JsonPropertyName("weight")]
|
||||
public required double Weight { get; init; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public required string Description { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signal conflict response.
|
||||
/// </summary>
|
||||
public sealed record SignalConflictResponse
|
||||
{
|
||||
[JsonPropertyName("signal_a")]
|
||||
public required string SignalA { get; init; }
|
||||
|
||||
[JsonPropertyName("signal_b")]
|
||||
public required string SignalB { get; init; }
|
||||
|
||||
[JsonPropertyName("conflict_type")]
|
||||
public required string ConflictType { get; init; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public required string Description { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Weight manifest reference.
|
||||
/// </summary>
|
||||
public sealed record WeightManifestReference
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
[JsonPropertyName("content_hash")]
|
||||
public required string ContentHash { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Weight manifest summary for listing.
|
||||
/// </summary>
|
||||
public sealed record WeightManifestSummary
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
[JsonPropertyName("effective_from")]
|
||||
public required DateTimeOffset EffectiveFrom { get; init; }
|
||||
|
||||
[JsonPropertyName("profile")]
|
||||
public required string Profile { get; init; }
|
||||
|
||||
[JsonPropertyName("content_hash")]
|
||||
public string? ContentHash { get; init; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Full weight manifest detail.
|
||||
/// </summary>
|
||||
public sealed record WeightManifestDetail
|
||||
{
|
||||
[JsonPropertyName("schema_version")]
|
||||
public required string SchemaVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
[JsonPropertyName("effective_from")]
|
||||
public required DateTimeOffset EffectiveFrom { get; init; }
|
||||
|
||||
[JsonPropertyName("profile")]
|
||||
public required string Profile { get; init; }
|
||||
|
||||
[JsonPropertyName("content_hash")]
|
||||
public string? ContentHash { get; init; }
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; init; }
|
||||
|
||||
[JsonPropertyName("weights")]
|
||||
public required WeightDefinitionsDto Weights { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Weight definitions DTO.
|
||||
/// </summary>
|
||||
public sealed record WeightDefinitionsDto
|
||||
{
|
||||
[JsonPropertyName("legacy")]
|
||||
public LegacyWeightsDto? Legacy { get; init; }
|
||||
|
||||
[JsonPropertyName("advisory")]
|
||||
public AdvisoryWeightsDto? Advisory { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legacy weights DTO.
|
||||
/// </summary>
|
||||
public sealed record LegacyWeightsDto
|
||||
{
|
||||
[JsonPropertyName("rch")]
|
||||
public double Rch { get; init; }
|
||||
|
||||
[JsonPropertyName("rts")]
|
||||
public double Rts { get; init; }
|
||||
|
||||
[JsonPropertyName("bkp")]
|
||||
public double Bkp { get; init; }
|
||||
|
||||
[JsonPropertyName("xpl")]
|
||||
public double Xpl { get; init; }
|
||||
|
||||
[JsonPropertyName("src")]
|
||||
public double Src { get; init; }
|
||||
|
||||
[JsonPropertyName("mit")]
|
||||
public double Mit { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Advisory weights DTO.
|
||||
/// </summary>
|
||||
public sealed record AdvisoryWeightsDto
|
||||
{
|
||||
[JsonPropertyName("cvss")]
|
||||
public double Cvss { get; init; }
|
||||
|
||||
[JsonPropertyName("epss")]
|
||||
public double Epss { get; init; }
|
||||
|
||||
[JsonPropertyName("reachability")]
|
||||
public double Reachability { get; init; }
|
||||
|
||||
[JsonPropertyName("exploit_maturity")]
|
||||
public double ExploitMaturity { get; init; }
|
||||
|
||||
[JsonPropertyName("patch_proof")]
|
||||
public double PatchProof { get; init; }
|
||||
}
|
||||
|
||||
#region TSF-011: Score Replay Models
|
||||
|
||||
/// <summary>
|
||||
/// Response for score replay endpoint.
|
||||
/// </summary>
|
||||
public sealed record ScoreReplayResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Base64-encoded DSSE envelope containing the signed replay log.
|
||||
/// </summary>
|
||||
[JsonPropertyName("signed_replay_log_dsse")]
|
||||
public required string SignedReplayLogDsse { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Rekor transparency log inclusion proof (if anchored).
|
||||
/// </summary>
|
||||
[JsonPropertyName("rekor_inclusion")]
|
||||
public RekorInclusionDto? RekorInclusion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Canonical input hashes for verification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("canonical_inputs")]
|
||||
public required IReadOnlyList<CanonicalInputDto> CanonicalInputs { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Transform versions used in scoring.
|
||||
/// </summary>
|
||||
[JsonPropertyName("transforms")]
|
||||
public required IReadOnlyList<TransformStepDto> Transforms { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Step-by-step algebra decisions.
|
||||
/// </summary>
|
||||
[JsonPropertyName("algebra_steps")]
|
||||
public required IReadOnlyList<AlgebraStepDto> AlgebraSteps { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The final computed score.
|
||||
/// </summary>
|
||||
[JsonPropertyName("final_score")]
|
||||
public required int FinalScore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the score was computed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("computed_at")]
|
||||
public required DateTimeOffset ComputedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rekor inclusion proof DTO.
|
||||
/// </summary>
|
||||
public sealed record RekorInclusionDto
|
||||
{
|
||||
[JsonPropertyName("log_index")]
|
||||
public required long LogIndex { get; init; }
|
||||
|
||||
[JsonPropertyName("root_hash")]
|
||||
public required string RootHash { get; init; }
|
||||
|
||||
[JsonPropertyName("tree_size")]
|
||||
public long? TreeSize { get; init; }
|
||||
|
||||
[JsonPropertyName("uuid")]
|
||||
public string? Uuid { get; init; }
|
||||
|
||||
[JsonPropertyName("integrated_time")]
|
||||
public DateTimeOffset? IntegratedTime { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Canonical input DTO for replay.
|
||||
/// </summary>
|
||||
public sealed record CanonicalInputDto
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonPropertyName("sha256")]
|
||||
public required string Sha256 { get; init; }
|
||||
|
||||
[JsonPropertyName("source_ref")]
|
||||
public string? SourceRef { get; init; }
|
||||
|
||||
[JsonPropertyName("size_bytes")]
|
||||
public long? SizeBytes { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform step DTO for replay.
|
||||
/// </summary>
|
||||
public sealed record TransformStepDto
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
[JsonPropertyName("params")]
|
||||
public IReadOnlyDictionary<string, object>? Params { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Algebra step DTO for replay.
|
||||
/// </summary>
|
||||
public sealed record AlgebraStepDto
|
||||
{
|
||||
[JsonPropertyName("signal")]
|
||||
public required string Signal { get; init; }
|
||||
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
[JsonPropertyName("w")]
|
||||
public required double Weight { get; init; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public required double Value { get; init; }
|
||||
|
||||
[JsonPropertyName("term")]
|
||||
public required double Term { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request for score verification.
|
||||
/// </summary>
|
||||
public sealed record ScoreVerifyRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The replay log DSSE envelope to verify.
|
||||
/// </summary>
|
||||
[JsonPropertyName("signed_replay_log_dsse")]
|
||||
public required string SignedReplayLogDsse { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Original inputs for replay verification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("original_inputs")]
|
||||
public ScoreVerifyInputs? OriginalInputs { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to verify Rekor inclusion.
|
||||
/// </summary>
|
||||
[JsonPropertyName("verify_rekor")]
|
||||
public bool VerifyRekor { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Original inputs for verification.
|
||||
/// </summary>
|
||||
public sealed record ScoreVerifyInputs
|
||||
{
|
||||
[JsonPropertyName("signals")]
|
||||
public SignalInputs? Signals { get; init; }
|
||||
|
||||
[JsonPropertyName("weight_manifest_version")]
|
||||
public string? WeightManifestVersion { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response from score verification.
|
||||
/// </summary>
|
||||
public sealed record ScoreVerifyResponse
|
||||
{
|
||||
[JsonPropertyName("verified")]
|
||||
public required bool Verified { get; init; }
|
||||
|
||||
[JsonPropertyName("replayed_score")]
|
||||
public required int ReplayedScore { get; init; }
|
||||
|
||||
[JsonPropertyName("original_score")]
|
||||
public required int OriginalScore { get; init; }
|
||||
|
||||
[JsonPropertyName("score_matches")]
|
||||
public required bool ScoreMatches { get; init; }
|
||||
|
||||
[JsonPropertyName("digest_matches")]
|
||||
public required bool DigestMatches { get; init; }
|
||||
|
||||
[JsonPropertyName("signature_valid")]
|
||||
public bool? SignatureValid { get; init; }
|
||||
|
||||
[JsonPropertyName("rekor_proof_valid")]
|
||||
public bool? RekorProofValid { get; init; }
|
||||
|
||||
[JsonPropertyName("differences")]
|
||||
public IReadOnlyList<VerificationDifferenceDto>? Differences { get; init; }
|
||||
|
||||
[JsonPropertyName("verified_at")]
|
||||
public required DateTimeOffset VerifiedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification difference DTO.
|
||||
/// </summary>
|
||||
public sealed record VerificationDifferenceDto
|
||||
{
|
||||
[JsonPropertyName("field")]
|
||||
public required string Field { get; init; }
|
||||
|
||||
[JsonPropertyName("expected")]
|
||||
public required string Expected { get; init; }
|
||||
|
||||
[JsonPropertyName("actual")]
|
||||
public required string Actual { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
Reference in New Issue
Block a user