Add Canonical JSON serialization library with tests and documentation
- Implemented CanonJson class for deterministic JSON serialization and hashing. - Added unit tests for CanonJson functionality, covering various scenarios including key sorting, handling of nested objects, arrays, and special characters. - Created project files for the Canonical JSON library and its tests, including necessary package references. - Added README.md for library usage and API reference. - Introduced RabbitMqIntegrationFactAttribute for conditional RabbitMQ integration tests.
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// ReachabilityDriftPredicate.cs
|
||||
// Sprint: SPRINT_3600_0004_0001_ui_evidence_chain
|
||||
// Task: UI-014
|
||||
// Description: DSSE predicate for reachability drift attestation.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Attestor.ProofChain.Predicates;
|
||||
|
||||
/// <summary>
|
||||
/// DSSE predicate for reachability drift attestation.
|
||||
/// predicateType: stellaops.dev/predicates/reachability-drift@v1
|
||||
/// </summary>
|
||||
public sealed record ReachabilityDriftPredicate
|
||||
{
|
||||
/// <summary>
|
||||
/// The predicate type URI for reachability drift attestations.
|
||||
/// </summary>
|
||||
public const string PredicateType = "stellaops.dev/predicates/reachability-drift@v1";
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the base (previous) image being compared.
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseImage")]
|
||||
public required DriftImageReference BaseImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the target (current) image being compared.
|
||||
/// </summary>
|
||||
[JsonPropertyName("targetImage")]
|
||||
public required DriftImageReference TargetImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan ID of the baseline scan.
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseScanId")]
|
||||
public required string BaseScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan ID of the head (current) scan.
|
||||
/// </summary>
|
||||
[JsonPropertyName("headScanId")]
|
||||
public required string HeadScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Summary of detected drift.
|
||||
/// </summary>
|
||||
[JsonPropertyName("drift")]
|
||||
public required DriftPredicateSummary Drift { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Metadata about the analysis performed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("analysis")]
|
||||
public required DriftAnalysisMetadata Analysis { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to a container image in drift analysis.
|
||||
/// </summary>
|
||||
public sealed record DriftImageReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Image name (repository/image).
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Image digest (sha256:...).
|
||||
/// </summary>
|
||||
[JsonPropertyName("digest")]
|
||||
public required string Digest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional tag at time of analysis.
|
||||
/// </summary>
|
||||
[JsonPropertyName("tag")]
|
||||
public string? Tag { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of drift detection results for the predicate.
|
||||
/// </summary>
|
||||
public sealed record DriftPredicateSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of sinks that became reachable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyReachableCount")]
|
||||
public required int NewlyReachableCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of sinks that became unreachable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyUnreachableCount")]
|
||||
public required int NewlyUnreachableCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Details of newly reachable sinks.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyReachable")]
|
||||
public required ImmutableArray<DriftedSinkPredicateSummary> NewlyReachable { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Details of newly unreachable (mitigated) sinks.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyUnreachable")]
|
||||
public required ImmutableArray<DriftedSinkPredicateSummary> NewlyUnreachable { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of a single drifted sink for inclusion in the predicate.
|
||||
/// </summary>
|
||||
public sealed record DriftedSinkPredicateSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique identifier for the sink node.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sinkNodeId")]
|
||||
public required string SinkNodeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Fully qualified symbol name of the sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Category of the sink (sql_injection, command_execution, etc.).
|
||||
/// </summary>
|
||||
[JsonPropertyName("sinkCategory")]
|
||||
public required string SinkCategory { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Kind of drift cause (guard_removed, new_route, dependency_change, etc.).
|
||||
/// </summary>
|
||||
[JsonPropertyName("causeKind")]
|
||||
public required string CauseKind { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable description of the cause.
|
||||
/// </summary>
|
||||
[JsonPropertyName("causeDescription")]
|
||||
public required string CauseDescription { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// CVE IDs associated with this sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("associatedCves")]
|
||||
public ImmutableArray<string> AssociatedCves { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Hash of the compressed path for verification.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pathHash")]
|
||||
public string? PathHash { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metadata about the drift analysis.
|
||||
/// </summary>
|
||||
public sealed record DriftAnalysisMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// When the analysis was performed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("analyzedAt")]
|
||||
public required DateTimeOffset AnalyzedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Information about the scanner that performed the analysis.
|
||||
/// </summary>
|
||||
[JsonPropertyName("scanner")]
|
||||
public required DriftScannerInfo Scanner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Content-addressed digest of the baseline call graph.
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseGraphDigest")]
|
||||
public required string BaseGraphDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Content-addressed digest of the head call graph.
|
||||
/// </summary>
|
||||
[JsonPropertyName("headGraphDigest")]
|
||||
public required string HeadGraphDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: digest of the code change facts used.
|
||||
/// </summary>
|
||||
[JsonPropertyName("codeChangesDigest")]
|
||||
public string? CodeChangesDigest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about the scanner that performed drift analysis.
|
||||
/// </summary>
|
||||
public sealed record DriftScannerInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the scanner.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Version of the scanner.
|
||||
/// </summary>
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional ruleset used for sink detection.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ruleset")]
|
||||
public string? Ruleset { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// ReachabilityDriftStatement.cs
|
||||
// Sprint: SPRINT_3600_0004_0001_ui_evidence_chain
|
||||
// Description: DSSE predicate for reachability drift attestation.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Attestor.ProofChain.Statements;
|
||||
|
||||
/// <summary>
|
||||
/// In-toto statement for reachability drift between scans.
|
||||
/// Predicate type: stellaops.dev/predicates/reachability-drift@v1
|
||||
/// </summary>
|
||||
public sealed record ReachabilityDriftStatement : InTotoStatement
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[JsonPropertyName("predicateType")]
|
||||
public override string PredicateType => "stellaops.dev/predicates/reachability-drift@v1";
|
||||
|
||||
/// <summary>
|
||||
/// The drift payload.
|
||||
/// </summary>
|
||||
[JsonPropertyName("predicate")]
|
||||
public required ReachabilityDriftPayload Predicate { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Payload for reachability drift statements.
|
||||
/// </summary>
|
||||
public sealed record ReachabilityDriftPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Base image reference (before).
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseImage")]
|
||||
public required ImageReference BaseImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Target image reference (after).
|
||||
/// </summary>
|
||||
[JsonPropertyName("targetImage")]
|
||||
public required ImageReference TargetImage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan ID of the base scan.
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseScanId")]
|
||||
public required string BaseScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan ID of the head scan.
|
||||
/// </summary>
|
||||
[JsonPropertyName("headScanId")]
|
||||
public required string HeadScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Drift summary.
|
||||
/// </summary>
|
||||
[JsonPropertyName("drift")]
|
||||
public required DriftSummary Drift { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Analysis metadata.
|
||||
/// </summary>
|
||||
[JsonPropertyName("analysis")]
|
||||
public required DriftAnalysisMetadata Analysis { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Image reference for drift comparison.
|
||||
/// </summary>
|
||||
public sealed record ImageReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Image name (e.g., "myregistry.io/app").
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Image digest (e.g., "sha256:...").
|
||||
/// </summary>
|
||||
[JsonPropertyName("digest")]
|
||||
public required string Digest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of reachability drift.
|
||||
/// </summary>
|
||||
public sealed record DriftSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// Count of newly reachable paths (NEW RISK).
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyReachableCount")]
|
||||
public required int NewlyReachableCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Count of newly unreachable paths (MITIGATED).
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyUnreachableCount")]
|
||||
public required int NewlyUnreachableCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Details of newly reachable sinks.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyReachable")]
|
||||
public ImmutableArray<DriftedSinkSummary> NewlyReachable { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Details of newly unreachable sinks.
|
||||
/// </summary>
|
||||
[JsonPropertyName("newlyUnreachable")]
|
||||
public ImmutableArray<DriftedSinkSummary> NewlyUnreachable { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Net change in reachable vulnerability paths.
|
||||
/// Positive = more risk, negative = less risk.
|
||||
/// </summary>
|
||||
[JsonPropertyName("netChange")]
|
||||
public int NetChange => NewlyReachableCount - NewlyUnreachableCount;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this drift should block a PR.
|
||||
/// </summary>
|
||||
[JsonPropertyName("shouldBlock")]
|
||||
public bool ShouldBlock => NewlyReachableCount > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Summary of a drifted sink.
|
||||
/// </summary>
|
||||
public sealed record DriftedSinkSummary
|
||||
{
|
||||
/// <summary>
|
||||
/// Sink node identifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sinkNodeId")]
|
||||
public required string SinkNodeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol name of the sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Category of the sink (e.g., "deserialization", "sql_injection").
|
||||
/// </summary>
|
||||
[JsonPropertyName("sinkCategory")]
|
||||
public required string SinkCategory { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Kind of change that caused the drift.
|
||||
/// </summary>
|
||||
[JsonPropertyName("causeKind")]
|
||||
public required string CauseKind { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable description of the cause.
|
||||
/// </summary>
|
||||
[JsonPropertyName("causeDescription")]
|
||||
public required string CauseDescription { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// File where the change occurred.
|
||||
/// </summary>
|
||||
[JsonPropertyName("changedFile")]
|
||||
public string? ChangedFile { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Line where the change occurred.
|
||||
/// </summary>
|
||||
[JsonPropertyName("changedLine")]
|
||||
public int? ChangedLine { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Associated CVE IDs.
|
||||
/// </summary>
|
||||
[JsonPropertyName("associatedCves")]
|
||||
public ImmutableArray<string> AssociatedCves { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Entry point method key.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entryMethodKey")]
|
||||
public string? EntryMethodKey { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Path length from entry to sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("pathLength")]
|
||||
public int? PathLength { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metadata about the drift analysis.
|
||||
/// </summary>
|
||||
public sealed record DriftAnalysisMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// When the analysis was performed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("analyzedAt")]
|
||||
public required DateTimeOffset AnalyzedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scanner information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("scanner")]
|
||||
public required DriftScannerInfo Scanner { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Digest of the base call graph.
|
||||
/// </summary>
|
||||
[JsonPropertyName("baseGraphDigest")]
|
||||
public required string BaseGraphDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Digest of the head call graph.
|
||||
/// </summary>
|
||||
[JsonPropertyName("headGraphDigest")]
|
||||
public required string HeadGraphDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm used for graph hashing.
|
||||
/// </summary>
|
||||
[JsonPropertyName("hashAlgorithm")]
|
||||
public string HashAlgorithm { get; init; } = "blake3";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scanner information for drift analysis.
|
||||
/// </summary>
|
||||
public sealed record DriftScannerInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Scanner name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scanner version.
|
||||
/// </summary>
|
||||
[JsonPropertyName("version")]
|
||||
public required string Version { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Ruleset used for analysis.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ruleset")]
|
||||
public string? Ruleset { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// ReachabilityWitnessStatement.cs
|
||||
// Sprint: SPRINT_3600_0004_0001_ui_evidence_chain
|
||||
// Description: DSSE predicate for individual reachability witness attestation.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Attestor.ProofChain.Statements;
|
||||
|
||||
/// <summary>
|
||||
/// In-toto statement for reachability witness attestation.
|
||||
/// Predicate type: stellaops.dev/predicates/reachability-witness@v1
|
||||
/// </summary>
|
||||
public sealed record ReachabilityWitnessStatement : InTotoStatement
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[JsonPropertyName("predicateType")]
|
||||
public override string PredicateType => "stellaops.dev/predicates/reachability-witness@v1";
|
||||
|
||||
/// <summary>
|
||||
/// The witness payload.
|
||||
/// </summary>
|
||||
[JsonPropertyName("predicate")]
|
||||
public required ReachabilityWitnessPayload Predicate { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Payload for reachability witness statements.
|
||||
/// </summary>
|
||||
public sealed record ReachabilityWitnessPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique witness identifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("witnessId")]
|
||||
public required string WitnessId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Scan ID that produced this witness.
|
||||
/// </summary>
|
||||
[JsonPropertyName("scanId")]
|
||||
public required string ScanId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerability identifier (internal).
|
||||
/// </summary>
|
||||
[JsonPropertyName("vulnId")]
|
||||
public required string VulnId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// CVE identifier if applicable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("cveId")]
|
||||
public string? CveId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("packageName")]
|
||||
public required string PackageName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package version.
|
||||
/// </summary>
|
||||
[JsonPropertyName("packageVersion")]
|
||||
public string? PackageVersion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package URL (purl).
|
||||
/// </summary>
|
||||
[JsonPropertyName("purl")]
|
||||
public string? Purl { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Confidence tier for reachability assessment.
|
||||
/// </summary>
|
||||
[JsonPropertyName("confidenceTier")]
|
||||
public required string ConfidenceTier { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Confidence score (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("confidenceScore")]
|
||||
public required double ConfidenceScore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the vulnerable code is reachable.
|
||||
/// </summary>
|
||||
[JsonPropertyName("isReachable")]
|
||||
public required bool IsReachable { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Call path from entry point to sink.
|
||||
/// </summary>
|
||||
[JsonPropertyName("callPath")]
|
||||
public ImmutableArray<WitnessCallPathNode> CallPath { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Entry point information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entrypoint")]
|
||||
public WitnessPathNode? Entrypoint { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Sink (vulnerable method) information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("sink")]
|
||||
public WitnessPathNode? Sink { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Security gates encountered along the path.
|
||||
/// </summary>
|
||||
[JsonPropertyName("gates")]
|
||||
public ImmutableArray<WitnessGateInfo> Gates { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Evidence metadata.
|
||||
/// </summary>
|
||||
[JsonPropertyName("evidence")]
|
||||
public required WitnessEvidenceMetadata Evidence { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the witness was observed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("observedAt")]
|
||||
public required DateTimeOffset ObservedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// VEX recommendation based on reachability.
|
||||
/// </summary>
|
||||
[JsonPropertyName("vexRecommendation")]
|
||||
public string? VexRecommendation { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Node in the witness call path.
|
||||
/// </summary>
|
||||
public sealed record WitnessCallPathNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Node identifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("nodeId")]
|
||||
public required string NodeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Source file path.
|
||||
/// </summary>
|
||||
[JsonPropertyName("file")]
|
||||
public string? File { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Line number.
|
||||
/// </summary>
|
||||
[JsonPropertyName("line")]
|
||||
public int? Line { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package name if external.
|
||||
/// </summary>
|
||||
[JsonPropertyName("package")]
|
||||
public string? Package { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this node was changed (for drift).
|
||||
/// </summary>
|
||||
[JsonPropertyName("isChanged")]
|
||||
public bool IsChanged { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Kind of change if changed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("changeKind")]
|
||||
public string? ChangeKind { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detailed path node for entry/sink.
|
||||
/// </summary>
|
||||
public sealed record WitnessPathNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Node identifier.
|
||||
/// </summary>
|
||||
[JsonPropertyName("nodeId")]
|
||||
public required string NodeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Source file path.
|
||||
/// </summary>
|
||||
[JsonPropertyName("file")]
|
||||
public string? File { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Line number.
|
||||
/// </summary>
|
||||
[JsonPropertyName("line")]
|
||||
public int? Line { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Package name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("package")]
|
||||
public string? Package { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Method name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("method")]
|
||||
public string? Method { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP route if entry point.
|
||||
/// </summary>
|
||||
[JsonPropertyName("httpRoute")]
|
||||
public string? HttpRoute { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// HTTP method if entry point.
|
||||
/// </summary>
|
||||
[JsonPropertyName("httpMethod")]
|
||||
public string? HttpMethod { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Security gate information in witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessGateInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of gate.
|
||||
/// </summary>
|
||||
[JsonPropertyName("gateType")]
|
||||
public required string GateType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Symbol name.
|
||||
/// </summary>
|
||||
[JsonPropertyName("symbol")]
|
||||
public required string Symbol { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Confidence in gate detection.
|
||||
/// </summary>
|
||||
[JsonPropertyName("confidence")]
|
||||
public required double Confidence { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Description of the gate.
|
||||
/// </summary>
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// File where gate is located.
|
||||
/// </summary>
|
||||
[JsonPropertyName("file")]
|
||||
public string? File { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Line number.
|
||||
/// </summary>
|
||||
[JsonPropertyName("line")]
|
||||
public int? Line { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evidence metadata for witness.
|
||||
/// </summary>
|
||||
public sealed record WitnessEvidenceMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Call graph hash.
|
||||
/// </summary>
|
||||
[JsonPropertyName("callGraphHash")]
|
||||
public string? CallGraphHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Surface hash.
|
||||
/// </summary>
|
||||
[JsonPropertyName("surfaceHash")]
|
||||
public string? SurfaceHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Analysis method used.
|
||||
/// </summary>
|
||||
[JsonPropertyName("analysisMethod")]
|
||||
public required string AnalysisMethod { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Tool version.
|
||||
/// </summary>
|
||||
[JsonPropertyName("toolVersion")]
|
||||
public string? ToolVersion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Hash algorithm used.
|
||||
/// </summary>
|
||||
[JsonPropertyName("hashAlgorithm")]
|
||||
public string HashAlgorithm { get; init; } = "blake3";
|
||||
}
|
||||
Reference in New Issue
Block a user