Complete Entrypoint Detection Re-Engineering Program (Sprints 0410-0415) and Sprint 3500.0002.0003 (Proof Replay + API)

Entrypoint Detection Program (100% complete):
- Sprint 0411: Semantic Entrypoint Engine - all 25 tasks DONE
- Sprint 0412: Temporal & Mesh Entrypoint - all 19 tasks DONE
- Sprint 0413: Speculative Execution Engine - all 19 tasks DONE
- Sprint 0414: Binary Intelligence - all 19 tasks DONE
- Sprint 0415: Predictive Risk Scoring - all tasks DONE

Key deliverables:
- SemanticEntrypoint schema with ApplicationIntent/CapabilityClass
- TemporalEntrypointGraph and MeshEntrypointGraph
- ShellSymbolicExecutor with PathEnumerator and PathConfidenceScorer
- CodeFingerprint index with symbol recovery
- RiskScore with multi-dimensional risk assessment

Sprint 3500.0002.0003 (Proof Replay + API):
- ManifestEndpoints with DSSE content negotiation
- Proof bundle endpoints by root hash
- IdempotencyMiddleware with RFC 9530 Content-Digest
- Rate limiting (100 req/hr per tenant)
- OpenAPI documentation updates

Tests: 357 EntryTrace tests pass, WebService tests blocked by pre-existing infrastructure issue
This commit is contained in:
StellaOps Bot
2025-12-20 17:46:27 +02:00
parent ce8cdcd23d
commit 3698ebf4a8
46 changed files with 4156 additions and 46 deletions

View File

@@ -0,0 +1,201 @@
// -----------------------------------------------------------------------------
// ManifestContracts.cs
// Sprint: SPRINT_3500_0002_0003_proof_replay_api
// Task: T1 - Scan Manifest Endpoint
// Description: Request/response contracts for scan manifest operations
// -----------------------------------------------------------------------------
using System.Text.Json.Serialization;
namespace StellaOps.Scanner.WebService.Contracts;
/// <summary>
/// Response for GET /scans/{scanId}/manifest endpoint.
/// </summary>
public sealed record ScanManifestResponse
{
/// <summary>Unique identifier for this manifest.</summary>
[JsonPropertyName("manifestId")]
public Guid ManifestId { get; init; }
/// <summary>Reference to the parent scan.</summary>
[JsonPropertyName("scanId")]
public Guid ScanId { get; init; }
/// <summary>SHA-256 hash of the canonical manifest content.</summary>
[JsonPropertyName("manifestHash")]
public string ManifestHash { get; init; } = string.Empty;
/// <summary>Hash of the input SBOM.</summary>
[JsonPropertyName("sbomHash")]
public string SbomHash { get; init; } = string.Empty;
/// <summary>Hash of the rules snapshot.</summary>
[JsonPropertyName("rulesHash")]
public string RulesHash { get; init; } = string.Empty;
/// <summary>Hash of the advisory feed snapshot.</summary>
[JsonPropertyName("feedHash")]
public string FeedHash { get; init; } = string.Empty;
/// <summary>Hash of the scoring policy.</summary>
[JsonPropertyName("policyHash")]
public string PolicyHash { get; init; } = string.Empty;
/// <summary>When the scan started (UTC ISO-8601).</summary>
[JsonPropertyName("scanStartedAt")]
public DateTimeOffset ScanStartedAt { get; init; }
/// <summary>When the scan completed (null if still running).</summary>
[JsonPropertyName("scanCompletedAt")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? ScanCompletedAt { get; init; }
/// <summary>Version of the scanner that created this manifest.</summary>
[JsonPropertyName("scannerVersion")]
public string ScannerVersion { get; init; } = string.Empty;
/// <summary>When this manifest was created.</summary>
[JsonPropertyName("createdAt")]
public DateTimeOffset CreatedAt { get; init; }
/// <summary>Content-Digest header value (RFC 9530).</summary>
[JsonPropertyName("contentDigest")]
public string ContentDigest { get; init; } = string.Empty;
}
/// <summary>
/// Response for GET /scans/{scanId}/manifest with DSSE envelope (Accept: application/dsse+json).
/// </summary>
public sealed record SignedScanManifestResponse
{
/// <summary>The scan manifest.</summary>
[JsonPropertyName("manifest")]
public ScanManifestResponse Manifest { get; init; } = new();
/// <summary>SHA-256 hash of the canonical manifest content.</summary>
[JsonPropertyName("manifestHash")]
public string ManifestHash { get; init; } = string.Empty;
/// <summary>The DSSE envelope containing the signed manifest.</summary>
[JsonPropertyName("envelope")]
public DsseEnvelopeDto Envelope { get; init; } = new();
/// <summary>When the manifest was signed (UTC).</summary>
[JsonPropertyName("signedAt")]
public DateTimeOffset SignedAt { get; init; }
/// <summary>Whether the signature is valid.</summary>
[JsonPropertyName("signatureValid")]
public bool SignatureValid { get; init; }
}
/// <summary>
/// Response for GET /scans/{scanId}/proofs/{rootHash} endpoint.
/// </summary>
public sealed record ProofBundleResponse
{
/// <summary>Reference to the parent scan.</summary>
[JsonPropertyName("scanId")]
public Guid ScanId { get; init; }
/// <summary>Root hash of the proof Merkle tree.</summary>
[JsonPropertyName("rootHash")]
public string RootHash { get; init; } = string.Empty;
/// <summary>Type of bundle: standard, extended, or minimal.</summary>
[JsonPropertyName("bundleType")]
public string BundleType { get; init; } = "standard";
/// <summary>SHA-256 hash of bundle content.</summary>
[JsonPropertyName("bundleHash")]
public string BundleHash { get; init; } = string.Empty;
/// <summary>Hash of the proof ledger.</summary>
[JsonPropertyName("ledgerHash")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? LedgerHash { get; init; }
/// <summary>Reference to the scan manifest hash.</summary>
[JsonPropertyName("manifestHash")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ManifestHash { get; init; }
/// <summary>Hash of the SBOM in this bundle.</summary>
[JsonPropertyName("sbomHash")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? SbomHash { get; init; }
/// <summary>Hash of the VEX in this bundle.</summary>
[JsonPropertyName("vexHash")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? VexHash { get; init; }
/// <summary>Key ID used for signing.</summary>
[JsonPropertyName("signatureKeyId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? SignatureKeyId { get; init; }
/// <summary>Signature algorithm.</summary>
[JsonPropertyName("signatureAlgorithm")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? SignatureAlgorithm { get; init; }
/// <summary>When this bundle was created.</summary>
[JsonPropertyName("createdAt")]
public DateTimeOffset CreatedAt { get; init; }
/// <summary>Optional expiration time for retention policies.</summary>
[JsonPropertyName("expiresAt")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? ExpiresAt { get; init; }
/// <summary>Whether the DSSE signature is valid.</summary>
[JsonPropertyName("signatureValid")]
public bool SignatureValid { get; init; }
/// <summary>Verification error message if failed.</summary>
[JsonPropertyName("verificationError")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? VerificationError { get; init; }
/// <summary>Content-Digest header value (RFC 9530).</summary>
[JsonPropertyName("contentDigest")]
public string ContentDigest { get; init; } = string.Empty;
}
/// <summary>
/// List response for GET /scans/{scanId}/proofs endpoint.
/// </summary>
public sealed record ProofBundleListResponse
{
/// <summary>List of proof bundles for this scan.</summary>
[JsonPropertyName("items")]
public IReadOnlyList<ProofBundleSummary> Items { get; init; } = [];
/// <summary>Total number of bundles.</summary>
[JsonPropertyName("total")]
public int Total { get; init; }
}
/// <summary>
/// Summary of a proof bundle for list responses.
/// </summary>
public sealed record ProofBundleSummary
{
/// <summary>Root hash of the proof Merkle tree.</summary>
[JsonPropertyName("rootHash")]
public string RootHash { get; init; } = string.Empty;
/// <summary>Type of bundle: standard, extended, or minimal.</summary>
[JsonPropertyName("bundleType")]
public string BundleType { get; init; } = "standard";
/// <summary>SHA-256 hash of bundle content.</summary>
[JsonPropertyName("bundleHash")]
public string BundleHash { get; init; } = string.Empty;
/// <summary>When this bundle was created.</summary>
[JsonPropertyName("createdAt")]
public DateTimeOffset CreatedAt { get; init; }
}