Merge branch 'main' of https://git.stella-ops.org/stella-ops.org/git.stella-ops.org
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
## Working Directory
|
||||
- Primary: `src/AdvisoryAI/**` (WebService, Worker, Hosting, plugins, tests).
|
||||
- Docs: `docs/advisory-ai/**`, `docs/policy/assistant-parameters.md`, `docs/sbom/*` when explicitly touched by sprint tasks.
|
||||
- Docs: `docs/advisory-ai/**`, `docs/policy/assistant-parameters.md`, `docs/modules/sbom-service/*` when explicitly touched by sprint tasks.
|
||||
- Shared libraries allowed only if referenced by Advisory AI projects; otherwise stay in-module.
|
||||
|
||||
## Required Reading (treat as read before DOING)
|
||||
|
||||
@@ -317,15 +317,18 @@ public sealed class PolicyBundleCompiler : IPolicyBundleCompiler
|
||||
private readonly IPolicyRuleGenerator _ruleGenerator;
|
||||
private readonly IPolicyBundleSigner? _signer;
|
||||
private readonly ILogger<PolicyBundleCompiler> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public PolicyBundleCompiler(
|
||||
IPolicyRuleGenerator ruleGenerator,
|
||||
IPolicyBundleSigner? signer,
|
||||
ILogger<PolicyBundleCompiler> logger)
|
||||
ILogger<PolicyBundleCompiler> logger,
|
||||
TimeProvider? timeProvider = null)
|
||||
{
|
||||
_ruleGenerator = ruleGenerator ?? throw new ArgumentNullException(nameof(ruleGenerator));
|
||||
_signer = signer;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public async Task<PolicyCompilationResult> CompileAsync(
|
||||
@@ -388,7 +391,7 @@ public sealed class PolicyBundleCompiler : IPolicyBundleCompiler
|
||||
Warnings = warnings,
|
||||
ValidationReport = validationReport,
|
||||
TestReport = testReport,
|
||||
CompiledAt = DateTime.UtcNow.ToString("O")
|
||||
CompiledAt = _timeProvider.GetUtcNow().ToString("O")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -425,7 +428,7 @@ public sealed class PolicyBundleCompiler : IPolicyBundleCompiler
|
||||
// Validate trust roots
|
||||
foreach (var root in bundle.TrustRoots)
|
||||
{
|
||||
if (root.ExpiresAt.HasValue && root.ExpiresAt.Value < DateTimeOffset.UtcNow)
|
||||
if (root.ExpiresAt.HasValue && root.ExpiresAt.Value < _timeProvider.GetUtcNow())
|
||||
{
|
||||
semanticWarnings.Add($"Trust root '{root.Principal.Id}' has expired");
|
||||
}
|
||||
@@ -489,7 +492,7 @@ public sealed class PolicyBundleCompiler : IPolicyBundleCompiler
|
||||
ContentDigest = contentDigest,
|
||||
Signature = string.Empty,
|
||||
Algorithm = "none",
|
||||
SignedAt = DateTime.UtcNow.ToString("O")
|
||||
SignedAt = _timeProvider.GetUtcNow().ToString("O")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -506,7 +509,7 @@ public sealed class PolicyBundleCompiler : IPolicyBundleCompiler
|
||||
Algorithm = signature.Algorithm,
|
||||
KeyId = options.KeyId,
|
||||
SignerIdentity = options.SignerIdentity,
|
||||
SignedAt = DateTime.UtcNow.ToString("O"),
|
||||
SignedAt = _timeProvider.GetUtcNow().ToString("O"),
|
||||
CertificateChain = signature.CertificateChain
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,17 +15,20 @@ public sealed class AiRemediationPlanner : IRemediationPlanner
|
||||
private readonly IRemediationPromptService _promptService;
|
||||
private readonly IRemediationInferenceClient _inferenceClient;
|
||||
private readonly IRemediationPlanStore _planStore;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public AiRemediationPlanner(
|
||||
IPackageVersionResolver versionResolver,
|
||||
IRemediationPromptService promptService,
|
||||
IRemediationInferenceClient inferenceClient,
|
||||
IRemediationPlanStore planStore)
|
||||
IRemediationPlanStore planStore,
|
||||
TimeProvider? timeProvider = null)
|
||||
{
|
||||
_versionResolver = versionResolver;
|
||||
_promptService = promptService;
|
||||
_inferenceClient = inferenceClient;
|
||||
_planStore = planStore;
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public async Task<RemediationPlan> GeneratePlanAsync(
|
||||
@@ -85,7 +88,7 @@ public sealed class AiRemediationPlanner : IRemediationPlanner
|
||||
NotReadyReason = notReadyReason,
|
||||
ConfidenceScore = inferenceResult.Confidence,
|
||||
ModelId = inferenceResult.ModelId,
|
||||
GeneratedAt = DateTime.UtcNow.ToString("O"),
|
||||
GeneratedAt = _timeProvider.GetUtcNow().ToString("O"),
|
||||
InputHashes = inputHashes,
|
||||
EvidenceRefs = new List<string> { versionResult.CurrentVersion, versionResult.RecommendedVersion }
|
||||
};
|
||||
|
||||
@@ -8,10 +8,12 @@ namespace StellaOps.AdvisoryAI.Remediation;
|
||||
public sealed class GitHubPullRequestGenerator : IPullRequestGenerator
|
||||
{
|
||||
private readonly IRemediationPlanStore _planStore;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public GitHubPullRequestGenerator(IRemediationPlanStore planStore)
|
||||
public GitHubPullRequestGenerator(IRemediationPlanStore planStore, TimeProvider? timeProvider = null)
|
||||
{
|
||||
_planStore = planStore;
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public string ScmType => "github";
|
||||
@@ -31,8 +33,8 @@ public sealed class GitHubPullRequestGenerator : IPullRequestGenerator
|
||||
BranchName = string.Empty,
|
||||
Status = PullRequestStatus.Failed,
|
||||
StatusMessage = plan.NotReadyReason ?? "Plan is not PR-ready",
|
||||
CreatedAt = DateTime.UtcNow.ToString("O"),
|
||||
UpdatedAt = DateTime.UtcNow.ToString("O")
|
||||
CreatedAt = _timeProvider.GetUtcNow().ToString("O"),
|
||||
UpdatedAt = _timeProvider.GetUtcNow().ToString("O")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@ public sealed class GitHubPullRequestGenerator : IPullRequestGenerator
|
||||
// 4. Create PR via GitHub API
|
||||
|
||||
var prId = $"gh-pr-{Guid.NewGuid():N}";
|
||||
var now = DateTime.UtcNow.ToString("O");
|
||||
var now = _timeProvider.GetUtcNow().ToString("O");
|
||||
|
||||
return new PullRequestResult
|
||||
{
|
||||
@@ -66,7 +68,7 @@ public sealed class GitHubPullRequestGenerator : IPullRequestGenerator
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// In a real implementation, this would query GitHub API
|
||||
var now = DateTime.UtcNow.ToString("O");
|
||||
var now = _timeProvider.GetUtcNow().ToString("O");
|
||||
|
||||
return Task.FromResult(new PullRequestResult
|
||||
{
|
||||
@@ -99,10 +101,10 @@ public sealed class GitHubPullRequestGenerator : IPullRequestGenerator
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static string GenerateBranchName(RemediationPlan plan)
|
||||
private string GenerateBranchName(RemediationPlan plan)
|
||||
{
|
||||
var vulnId = plan.Request.VulnerabilityId.Replace(":", "-").ToLowerInvariant();
|
||||
var timestamp = DateTime.UtcNow.ToString("yyyyMMdd");
|
||||
var timestamp = _timeProvider.GetUtcNow().ToString("yyyyMMdd");
|
||||
return $"stellaops/fix-{vulnId}-{timestamp}";
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@ namespace StellaOps.AdvisoryAI.Remediation;
|
||||
/// </summary>
|
||||
public sealed class GitLabMergeRequestGenerator : IPullRequestGenerator
|
||||
{
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public GitLabMergeRequestGenerator(TimeProvider? timeProvider = null)
|
||||
{
|
||||
_timeProvider = timeProvider ?? TimeProvider.System;
|
||||
}
|
||||
|
||||
public string ScmType => "gitlab";
|
||||
|
||||
public Task<PullRequestResult> CreatePullRequestAsync(
|
||||
@@ -23,14 +30,14 @@ public sealed class GitLabMergeRequestGenerator : IPullRequestGenerator
|
||||
BranchName = string.Empty,
|
||||
Status = PullRequestStatus.Failed,
|
||||
StatusMessage = plan.NotReadyReason ?? "Plan is not MR-ready",
|
||||
CreatedAt = DateTime.UtcNow.ToString("O"),
|
||||
UpdatedAt = DateTime.UtcNow.ToString("O")
|
||||
CreatedAt = _timeProvider.GetUtcNow().ToString("O"),
|
||||
UpdatedAt = _timeProvider.GetUtcNow().ToString("O")
|
||||
});
|
||||
}
|
||||
|
||||
var branchName = GenerateBranchName(plan);
|
||||
var mrId = $"gl-mr-{Guid.NewGuid():N}";
|
||||
var now = DateTime.UtcNow.ToString("O");
|
||||
var now = _timeProvider.GetUtcNow().ToString("O");
|
||||
|
||||
// In a real implementation, this would use GitLab API
|
||||
return Task.FromResult(new PullRequestResult
|
||||
@@ -50,7 +57,7 @@ public sealed class GitLabMergeRequestGenerator : IPullRequestGenerator
|
||||
string prId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var now = DateTime.UtcNow.ToString("O");
|
||||
var now = _timeProvider.GetUtcNow().ToString("O");
|
||||
return Task.FromResult(new PullRequestResult
|
||||
{
|
||||
PrId = prId,
|
||||
@@ -80,10 +87,10 @@ public sealed class GitLabMergeRequestGenerator : IPullRequestGenerator
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static string GenerateBranchName(RemediationPlan plan)
|
||||
private string GenerateBranchName(RemediationPlan plan)
|
||||
{
|
||||
var vulnId = plan.Request.VulnerabilityId.Replace(":", "-").ToLowerInvariant();
|
||||
var timestamp = DateTime.UtcNow.ToString("yyyyMMdd");
|
||||
var timestamp = _timeProvider.GetUtcNow().ToString("yyyyMMdd");
|
||||
return $"stellaops/fix-{vulnId}-{timestamp}";
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,9 @@ public class SignedModelBundleManagerTests
|
||||
|
||||
var envelopePath = Path.Combine(tempRoot, "signature.dsse");
|
||||
var envelopeJson = await File.ReadAllTextAsync(envelopePath, CancellationToken.None);
|
||||
var envelope = JsonSerializer.Deserialize<ModelBundleSignatureEnvelope>(envelopeJson);
|
||||
var envelope = JsonSerializer.Deserialize<ModelBundleSignatureEnvelope>(
|
||||
envelopeJson,
|
||||
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });
|
||||
Assert.NotNull(envelope);
|
||||
|
||||
var payloadJson = Encoding.UTF8.GetString(Convert.FromBase64String(envelope!.Payload));
|
||||
|
||||
Reference in New Issue
Block a user