Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.

This commit is contained in:
StellaOps Bot
2025-12-26 21:54:17 +02:00
parent 335ff7da16
commit c2b9cd8d1f
3717 changed files with 264714 additions and 48202 deletions

View File

@@ -5421,6 +5421,11 @@ internal static class CommandFactory
bundle.Add(bundleBuild);
bundle.Add(bundleVerify);
// Sprint: SPRINT_20251228_002_BE_oci_attestation_attach (T3)
// OCI attestation attachment workflow
var attach = BuildOciAttachCommand(services, verboseOption, cancellationToken);
var ociList = BuildOciListCommand(services, verboseOption, cancellationToken);
attest.Add(sign);
attest.Add(verify);
attest.Add(list);
@@ -5428,10 +5433,254 @@ internal static class CommandFactory
attest.Add(fetch);
attest.Add(key);
attest.Add(bundle);
attest.Add(attach); // stella attest attach --image ...
attest.Add(ociList); // stella attest oci-list --image ...
// Sprint: SPRINT_20251228_002_BE_oci_attestation_attach (T4)
// OCI attestation verification workflow
var ociVerify = BuildOciVerifyCommand(services, verboseOption, cancellationToken);
attest.Add(ociVerify); // stella attest oci-verify --image ...
return attest;
}
/// <summary>
/// Builds 'attest attach' subcommand for OCI attestation attachment.
/// Sprint: SPRINT_20251228_002_BE_oci_attestation_attach (T3)
/// </summary>
private static Command BuildOciAttachCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var imageOption = new Option<string>("--image", new[] { "-i" })
{
Description = "OCI image reference (registry/repo@sha256:... or registry/repo:tag)",
Required = true
};
var attestationOption = new Option<string>("--attestation", new[] { "-a" })
{
Description = "Path to DSSE attestation JSON file",
Required = true
};
var predicateTypeOption = new Option<string?>("--predicate-type", new[] { "-t" })
{
Description = "Predicate type URI (auto-detected from attestation if not specified)"
};
var signOption = new Option<bool>("--sign", new[] { "-s" })
{
Description = "Sign the attestation before attaching"
};
var keyOption = new Option<string?>("--key", new[] { "-k" })
{
Description = "Path to private key for signing (PEM or PKCS#8)"
};
var keylessOption = new Option<bool>("--sign-keyless")
{
Description = "Use Sigstore keyless signing (OIDC)"
};
var replaceOption = new Option<bool>("--replace")
{
Description = "Replace existing attestation with same predicate type"
};
var rekorOption = new Option<bool>("--rekor")
{
Description = "Record attestation in Sigstore Rekor transparency log"
};
var attach = new Command("attach", "Attach a DSSE attestation to an OCI artifact in registry")
{
imageOption,
attestationOption,
predicateTypeOption,
signOption,
keyOption,
keylessOption,
replaceOption,
rekorOption,
verboseOption
};
attach.SetAction(async (parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption) ?? string.Empty;
var attestationPath = parseResult.GetValue(attestationOption) ?? string.Empty;
var predicateType = parseResult.GetValue(predicateTypeOption);
var sign = parseResult.GetValue(signOption);
var keyPath = parseResult.GetValue(keyOption);
var keyless = parseResult.GetValue(keylessOption);
var replace = parseResult.GetValue(replaceOption);
var rekor = parseResult.GetValue(rekorOption);
var verbose = parseResult.GetValue(verboseOption);
return await CommandHandlers.HandleOciAttestAttachAsync(
services,
image,
attestationPath,
predicateType,
sign,
keyPath,
keyless,
replace,
rekor,
verbose,
cancellationToken);
});
return attach;
}
/// <summary>
/// Builds 'attest oci-list' subcommand for listing OCI attestations.
/// Sprint: SPRINT_20251228_002_BE_oci_attestation_attach (T3)
/// </summary>
private static Command BuildOciListCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var imageOption = new Option<string>("--image", new[] { "-i" })
{
Description = "OCI image reference",
Required = true
};
var formatOption = new Option<string?>("--format", new[] { "-f" })
{
Description = "Output format (json, table). Default: table"
};
var ociList = new Command("oci-list", "List attestations attached to an OCI artifact in registry")
{
imageOption,
formatOption,
verboseOption
};
ociList.SetAction(async (parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption) ?? string.Empty;
var format = parseResult.GetValue(formatOption) ?? "table";
var verbose = parseResult.GetValue(verboseOption);
return await CommandHandlers.HandleOciAttestListAsync(
services,
image,
format,
verbose,
cancellationToken);
});
return ociList;
}
/// <summary>
/// Builds 'attest oci-verify' subcommand for verifying OCI attestations.
/// Sprint: SPRINT_20251228_002_BE_oci_attestation_attach (T4)
/// </summary>
private static Command BuildOciVerifyCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
var imageOption = new Option<string>("--image", new[] { "-i" })
{
Description = "OCI image reference (registry/repo@sha256:... or registry/repo:tag)",
Required = true
};
var predicateTypeOption = new Option<string?>("--predicate-type", new[] { "-t" })
{
Description = "Filter by predicate type URI (verifies at least one attestation matches)"
};
var policyOption = new Option<string?>("--policy", new[] { "-p" })
{
Description = "Path to verification policy JSON/Rego file"
};
var rootOption = new Option<string?>("--root")
{
Description = "Path to trusted root certificate (PEM format) for signature verification"
};
var keyOption = new Option<string?>("--key", new[] { "-k" })
{
Description = "Path to public key (PEM format) for signature verification"
};
var rekorOption = new Option<bool>("--rekor")
{
Description = "Verify inclusion in Sigstore Rekor transparency log"
};
var strictOption = new Option<bool>("--strict")
{
Description = "Fail if any attestation fails verification (default: fail on no valid attestations)"
};
var formatOption = new Option<string?>("--format", new[] { "-f" })
{
Description = "Output format (json, table). Default: table"
};
var outputOption = new Option<string?>("--output", new[] { "-o" })
{
Description = "Write verification report to file"
};
var ociVerify = new Command("oci-verify", "Verify attestations attached to an OCI artifact in registry")
{
imageOption,
predicateTypeOption,
policyOption,
rootOption,
keyOption,
rekorOption,
strictOption,
formatOption,
outputOption,
verboseOption
};
ociVerify.SetAction(async (parseResult, ct) =>
{
var image = parseResult.GetValue(imageOption) ?? string.Empty;
var predicateType = parseResult.GetValue(predicateTypeOption);
var policy = parseResult.GetValue(policyOption);
var root = parseResult.GetValue(rootOption);
var key = parseResult.GetValue(keyOption);
var rekor = parseResult.GetValue(rekorOption);
var strict = parseResult.GetValue(strictOption);
var format = parseResult.GetValue(formatOption) ?? "table";
var output = parseResult.GetValue(outputOption);
var verbose = parseResult.GetValue(verboseOption);
return await CommandHandlers.HandleOciAttestVerifyAsync(
services,
image,
predicateType,
policy,
root,
key,
rekor,
strict,
format,
output,
verbose,
cancellationToken);
});
return ociVerify;
}
private static Command BuildRiskProfileCommand(Option<bool> verboseOption, CancellationToken cancellationToken)
{
_ = cancellationToken;