feat: Implement ScannerSurfaceSecretConfigurator for web service options
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added ScannerSurfaceSecretConfigurator to configure ScannerWebServiceOptions using surface secrets.
- Integrated ISurfaceSecretProvider to fetch and apply secrets for artifact store configuration.
- Enhanced logging for secret retrieval and application processes.

feat: Implement ScannerStorageSurfaceSecretConfigurator for worker options

- Introduced ScannerStorageSurfaceSecretConfigurator to configure ScannerStorageOptions with surface secrets.
- Utilized ISurfaceSecretProvider to retrieve and apply secrets for object store settings.
- Improved logging for secret handling and configuration.

feat: Create SurfaceManifestPublisher for publishing surface manifests

- Developed SurfaceManifestPublisher to handle the creation and storage of surface manifests.
- Implemented methods for serializing manifest documents and storing payloads in the object store.
- Added dual write functionality for mirror storage of manifests.

feat: Add SurfaceManifestStageExecutor for processing scan stages

- Created SurfaceManifestStageExecutor to execute the manifest publishing stage in scan jobs.
- Integrated with SurfaceManifestPublisher to publish manifests based on collected payloads.
- Enhanced logging for job processing and manifest storage.

feat: Define SurfaceManifest models for manifest structure

- Established SurfaceManifestDocument, SurfaceManifestSource, SurfaceManifestArtifact, and SurfaceManifestStorage records.
- Implemented serialization attributes for JSON handling of manifest models.

feat: Implement CasAccessSecret and SurfaceSecretParser for secret handling

- Created CasAccessSecret record to represent surface access secrets.
- Developed SurfaceSecretParser to parse and validate surface secrets from JSON payloads.

test: Add unit tests for CasAccessSecretParser

- Implemented tests for parsing CasAccessSecret from JSON payloads and metadata fallbacks.
- Verified expected values and behavior for secret parsing logic.

test: Add unit tests for ScannerSurfaceSecretConfigurator

- Created tests for ScannerSurfaceSecretConfigurator to ensure correct application of surface secrets to web service options.
- Validated artifact store settings after configuration.

test: Add unit tests for ScannerStorageSurfaceSecretConfigurator

- Implemented tests for ScannerStorageSurfaceSecretConfigurator to verify correct application of surface secrets to storage options.
- Ensured accurate configuration of object store settings.
This commit is contained in:
master
2025-11-06 18:49:23 +02:00
parent e536492da9
commit 18f28168f0
33 changed files with 2066 additions and 621 deletions

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.Scanner.Surface.FS;
/// <summary>
/// Canonical manifest describing surface artefacts produced for a scan.
/// </summary>
public sealed record SurfaceManifestDocument
{
public const string DefaultSchema = "stellaops.surface.manifest@1";
[JsonPropertyName("schema")]
public string Schema { get; init; } = DefaultSchema;
[JsonPropertyName("tenant")]
public string Tenant { get; init; } = string.Empty;
[JsonPropertyName("imageDigest")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ImageDigest { get; init; }
= null;
[JsonPropertyName("scanId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ScanId { get; init; }
= null;
[JsonPropertyName("generatedAt")]
public DateTimeOffset GeneratedAt { get; init; }
= DateTimeOffset.UtcNow;
[JsonPropertyName("source")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SurfaceManifestSource? Source { get; init; }
= null;
[JsonPropertyName("artifacts")]
public IReadOnlyList<SurfaceManifestArtifact> Artifacts { get; init; }
= ImmutableArray<SurfaceManifestArtifact>.Empty;
}
/// <summary>
/// Identifies the producer of the manifest.
/// </summary>
public sealed record SurfaceManifestSource
{
[JsonPropertyName("component")]
public string Component { get; init; } = "scanner.worker";
[JsonPropertyName("version")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Version { get; init; }
= null;
[JsonPropertyName("workerInstance")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? WorkerInstance { get; init; }
= null;
[JsonPropertyName("attempt")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Attempt { get; init; }
= null;
}
/// <summary>
/// Describes a surface artefact referenced by the manifest.
/// </summary>
public sealed record SurfaceManifestArtifact
{
[JsonPropertyName("kind")]
public string Kind { get; init; } = string.Empty;
[JsonPropertyName("uri")]
public string Uri { get; init; } = string.Empty;
[JsonPropertyName("digest")]
public string Digest { get; init; } = string.Empty;
[JsonPropertyName("mediaType")]
public string MediaType { get; init; } = string.Empty;
[JsonPropertyName("format")]
public string Format { get; init; } = string.Empty;
[JsonPropertyName("sizeBytes")]
public long SizeBytes { get; init; }
= 0;
[JsonPropertyName("view")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? View { get; init; }
= null;
[JsonPropertyName("storage")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public SurfaceManifestStorage? Storage { get; init; }
= null;
[JsonPropertyName("metadata")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyDictionary<string, string>? Metadata { get; init; }
= null;
}
/// <summary>
/// Storage descriptor for an artefact.
/// </summary>
public sealed record SurfaceManifestStorage
{
[JsonPropertyName("bucket")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Bucket { get; init; }
= null;
[JsonPropertyName("objectKey")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ObjectKey { get; init; }
= null;
[JsonPropertyName("sizeBytes")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public long? SizeBytes { get; init; }
= null;
[JsonPropertyName("contentType")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ContentType { get; init; }
= null;
}
/// <summary>
/// Result from publishing a surface manifest.
/// </summary>
public sealed record SurfaceManifestPublishResult(
string ManifestDigest,
string ManifestUri,
string ArtifactId,
SurfaceManifestDocument Document);