old sprints work, new sprints for exposing functionality via cli, improve code_of_conduct and other agents instructions
This commit is contained in:
468
src/Cli/StellaOps.Cli/Services/Models/WitnessModels.cs
Normal file
468
src/Cli/StellaOps.Cli/Services/Models/WitnessModels.cs
Normal file
@@ -0,0 +1,468 @@
|
||||
// <copyright file="WitnessModels.cs" company="StellaOps">
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
// Sprint: SPRINT_20260112_014_CLI_witness_commands (CLI-WIT-001)
|
||||
// </copyright>
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Cli.Services.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Request for listing witnesses.
|
||||
/// </summary>
|
||||
public sealed record WitnessListRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Filter by scan ID.
|
||||
/// </summary>
|
||||
public string? ScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Filter by vulnerability ID (e.g., CVE-2024-1234).
|
||||
/// </summary>
|
||||
public string? VulnerabilityId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Filter by component PURL.
|
||||
/// </summary>
|
||||
public string? ComponentPurl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Filter by predicate type.
|
||||
/// </summary>
|
||||
public string? PredicateType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of results.
|
||||
/// </summary>
|
||||
public int? Limit { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Continuation token for pagination.
|
||||
/// </summary>
|
||||
public string? ContinuationToken { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Tenant ID.
|
||||
/// </summary>
|
||||
public string? TenantId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response for listing witnesses.
|
||||
/// </summary>
|
||||
public sealed record WitnessListResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// List of witness summaries.
|
||||
/// </summary>
|
||||
[JsonPropertyName("witnesses")]
|
||||
public IReadOnlyList<WitnessSummary> Witnesses { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Continuation token for next page.
|
||||
/// </summary>
|
||||
[JsonPropertyName("continuation_token")]
|
||||
public string? ContinuationToken { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Total count of matching witnesses.
|
||||
/// </summary>
|
||||
[JsonPropertyName("total_count")]
|
||||
public int TotalCount { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of a witness for list views.
|
||||
/// </summary>
|
||||
public sealed record WitnessSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// Content-addressed witness ID.
|
||||
/// </summary>
|
||||
[JsonPropertyName("witness_id")]
|
||||
public required string WitnessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerability ID.
|
||||
/// </summary>
|
||||
[JsonPropertyName("vulnerability_id")]
|
||||
public string? VulnerabilityId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Component PURL.
|
||||
/// </summary>
|
||||
[JsonPropertyName("component_purl")]
|
||||
public string? ComponentPurl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Entrypoint name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entrypoint")]
|
||||
public string? Entrypoint { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sink symbol.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sink")]
|
||||
public string? Sink { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Path length.
|
||||
/// </summary>
|
||||
[JsonPropertyName("path_length")]
|
||||
public int PathLength { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Predicate type URI.
|
||||
/// </summary>
|
||||
[JsonPropertyName("predicate_type")]
|
||||
public string? PredicateType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the witness has a valid DSSE signature.
|
||||
/// </summary>
|
||||
[JsonPropertyName("is_signed")]
|
||||
public bool IsSigned { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the witness was created.
|
||||
/// </summary>
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTimeOffset CreatedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detailed witness response.
|
||||
/// </summary>
|
||||
public sealed record WitnessDetailResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Schema version.
|
||||
/// </summary>
|
||||
[JsonPropertyName("witness_schema")]
|
||||
public string? WitnessSchema { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Content-addressed witness ID.
|
||||
/// </summary>
|
||||
[JsonPropertyName("witness_id")]
|
||||
public required string WitnessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Artifact information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("artifact")]
|
||||
public WitnessArtifactInfo? Artifact { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerability information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("vuln")]
|
||||
public WitnessVulnInfo? Vuln { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Entrypoint information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entrypoint")]
|
||||
public WitnessEntrypointInfo? Entrypoint { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Call path from entrypoint to sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("path")]
|
||||
public IReadOnlyList<WitnessPathStep>? Path { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sink information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sink")]
|
||||
public WitnessSinkInfo? Sink { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Detected gates along the path.
|
||||
/// </summary>
|
||||
[JsonPropertyName("gates")]
|
||||
public IReadOnlyList<WitnessGateInfo>? Gates { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Evidence digests.
|
||||
/// </summary>
|
||||
[JsonPropertyName("evidence")]
|
||||
public WitnessEvidenceInfo? Evidence { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the witness was observed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("observed_at")]
|
||||
public DateTimeOffset ObservedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Path hash for deterministic joining.
|
||||
/// Sprint: SPRINT_20260112_004_SCANNER_path_witness_nodehash
|
||||
/// </summary>
|
||||
[JsonPropertyName("path_hash")]
|
||||
public string? PathHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Top-K node hashes along the path.
|
||||
/// Sprint: SPRINT_20260112_004_SCANNER_path_witness_nodehash
|
||||
/// </summary>
|
||||
[JsonPropertyName("node_hashes")]
|
||||
public IReadOnlyList<string>? NodeHashes { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Evidence URIs for traceability.
|
||||
/// </summary>
|
||||
[JsonPropertyName("evidence_uris")]
|
||||
public IReadOnlyList<string>? EvidenceUris { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Predicate type URI.
|
||||
/// </summary>
|
||||
[JsonPropertyName("predicate_type")]
|
||||
public string? PredicateType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// DSSE envelope if signed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("dsse_envelope")]
|
||||
public WitnessDsseEnvelope? DsseEnvelope { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Artifact information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessArtifactInfo
|
||||
{
|
||||
[JsonPropertyName("sbom_digest")]
|
||||
public string? SbomDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("component_purl")]
|
||||
public string? ComponentPurl { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerability information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessVulnInfo
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string? Id { get; init; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string? Source { get; init; }
|
||||
|
||||
[JsonPropertyName("affected_range")]
|
||||
public string? AffectedRange { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entrypoint information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessEntrypointInfo
|
||||
{
|
||||
[JsonPropertyName("kind")]
|
||||
public string? Kind { get; init; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; init; }
|
||||
|
||||
[JsonPropertyName("symbol_id")]
|
||||
public string? SymbolId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A step in the call path.
|
||||
/// </summary>
|
||||
public sealed record WitnessPathStep
|
||||
{
|
||||
[JsonPropertyName("symbol")]
|
||||
public string? Symbol { get; init; }
|
||||
|
||||
[JsonPropertyName("symbol_id")]
|
||||
public string? SymbolId { get; init; }
|
||||
|
||||
[JsonPropertyName("file")]
|
||||
public string? File { get; init; }
|
||||
|
||||
[JsonPropertyName("line")]
|
||||
public int? Line { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sink information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessSinkInfo
|
||||
{
|
||||
[JsonPropertyName("symbol")]
|
||||
public string? Symbol { get; init; }
|
||||
|
||||
[JsonPropertyName("symbol_id")]
|
||||
public string? SymbolId { get; init; }
|
||||
|
||||
[JsonPropertyName("sink_type")]
|
||||
public string? SinkType { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gate (guard/control) information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessGateInfo
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public string? Type { get; init; }
|
||||
|
||||
[JsonPropertyName("guard_symbol")]
|
||||
public string? GuardSymbol { get; init; }
|
||||
|
||||
[JsonPropertyName("confidence")]
|
||||
public double Confidence { get; init; }
|
||||
|
||||
[JsonPropertyName("detail")]
|
||||
public string? Detail { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evidence information in a witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessEvidenceInfo
|
||||
{
|
||||
[JsonPropertyName("callgraph_digest")]
|
||||
public string? CallgraphDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("surface_digest")]
|
||||
public string? SurfaceDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("analysis_config_digest")]
|
||||
public string? AnalysisConfigDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("build_id")]
|
||||
public string? BuildId { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DSSE envelope information.
|
||||
/// </summary>
|
||||
public sealed record WitnessDsseEnvelope
|
||||
{
|
||||
[JsonPropertyName("payload_type")]
|
||||
public string? PayloadType { get; init; }
|
||||
|
||||
[JsonPropertyName("payload")]
|
||||
public string? Payload { get; init; }
|
||||
|
||||
[JsonPropertyName("signatures")]
|
||||
public IReadOnlyList<WitnessDsseSignature>? Signatures { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DSSE signature information.
|
||||
/// </summary>
|
||||
public sealed record WitnessDsseSignature
|
||||
{
|
||||
[JsonPropertyName("keyid")]
|
||||
public string? KeyId { get; init; }
|
||||
|
||||
[JsonPropertyName("sig")]
|
||||
public string? Signature { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Response for witness verification.
|
||||
/// </summary>
|
||||
public sealed record WitnessVerifyResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether verification succeeded.
|
||||
/// </summary>
|
||||
[JsonPropertyName("verified")]
|
||||
public bool Verified { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Verification status code.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
public string? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Detailed verification message.
|
||||
/// </summary>
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// DSSE verification details.
|
||||
/// </summary>
|
||||
[JsonPropertyName("dsse")]
|
||||
public WitnessDsseVerifyInfo? Dsse { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Content hash verification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("content_hash")]
|
||||
public WitnessContentHashInfo? ContentHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Verification timestamp.
|
||||
/// </summary>
|
||||
[JsonPropertyName("verified_at")]
|
||||
public DateTimeOffset VerifiedAt { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DSSE verification details.
|
||||
/// </summary>
|
||||
public sealed record WitnessDsseVerifyInfo
|
||||
{
|
||||
[JsonPropertyName("envelope_valid")]
|
||||
public bool EnvelopeValid { get; init; }
|
||||
|
||||
[JsonPropertyName("signature_count")]
|
||||
public int SignatureCount { get; init; }
|
||||
|
||||
[JsonPropertyName("valid_signatures")]
|
||||
public int ValidSignatures { get; init; }
|
||||
|
||||
[JsonPropertyName("signer_identities")]
|
||||
public IReadOnlyList<string>? SignerIdentities { get; init; }
|
||||
|
||||
[JsonPropertyName("predicate_type")]
|
||||
public string? PredicateType { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Content hash verification details.
|
||||
/// </summary>
|
||||
public sealed record WitnessContentHashInfo
|
||||
{
|
||||
[JsonPropertyName("expected")]
|
||||
public string? Expected { get; init; }
|
||||
|
||||
[JsonPropertyName("actual")]
|
||||
public string? Actual { get; init; }
|
||||
|
||||
[JsonPropertyName("match")]
|
||||
public bool Match { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export format for witnesses.
|
||||
/// </summary>
|
||||
public enum WitnessExportFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Raw JSON witness payload.
|
||||
/// </summary>
|
||||
Json,
|
||||
|
||||
/// <summary>
|
||||
/// DSSE-signed envelope.
|
||||
/// </summary>
|
||||
Dsse,
|
||||
|
||||
/// <summary>
|
||||
/// SARIF format.
|
||||
/// </summary>
|
||||
Sarif
|
||||
}
|
||||
Reference in New Issue
Block a user