feat(audit): annotate Platform + Notify + Scheduler + ReleaseOrchestrator (Batch 2b)

Platform (~40 state-changing endpoints annotated):
- EnvironmentSettingsAdmin: update/delete environment settings
- IdentityProvider: create/update/delete/enable/disable/test/apply
- CryptoProviderAdmin: update/delete crypto preferences
- AdministrationTrustSigning: create/rotate/revoke keys, register/block/unblock issuers,
  register/revoke certificates, configure transparency log
- PlatformEndpoints: quota alerts, onboarding complete/skip, preferences update, dashboard profile create
- SetupEndpoints: create session, execute/skip steps, finalize setup
- ScoreEndpoints: evaluate/verify score
- ScriptEndpoints: create/update/delete scripts
- ReleaseOrchestratorEnvironment: CRUD environments/targets/freeze-windows

Notify (~30 state-changing endpoints annotated):
- NotifyApi (v2): rules CRUD, templates CRUD, incident ack/resolve
- RuleEndpoints (v2): create/update/delete rules
- TemplateEndpoints (v2): create/update/delete templates
- EscalationEndpoints: CRUD policies, schedules, overrides; start/escalate/stop
- QuietHoursEndpoints: create/update/delete calendars
- ThrottleEndpoints: update/delete config
- OperatorOverrideEndpoints: create/revoke overrides

Scheduler (~10 state-changing endpoints annotated):
- ScheduleEndpoints: create/update/delete/pause/resume schedules
- RunEndpoints: create/cancel/retry runs
- GraphJobEndpoints: create build/overlay graph jobs
- PolicyRunEndpoints: create policy run
- Added StellaOps.Audit.Emission project reference + AddAuditEmission() registration
- Fixed pre-existing ScanJobPlugin.cs build error (Success -> Valid)

ReleaseOrchestrator (~25 state-changing endpoints annotated):
- ReleaseEndpoints: create/update/delete/ready/promote/deploy/rollback/clone releases,
  add/update/remove components
- ApprovalEndpoints: approve/reject/batch-approve/batch-reject
- DeploymentEndpoints: create/pause/resume/cancel/rollback/retry deployments
- EvidenceEndpoints: verify evidence
- ScriptsEndpoints: create/update/delete scripts
- ReleaseDashboardEndpoints: approve/reject promotions
- ReleaseControlV2Endpoints: approval decision, rollback run

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-04-09 11:40:02 +03:00
parent d4d75200c5
commit 54e7f871a3
30 changed files with 265 additions and 121 deletions

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Audit.Emission;
using StellaOps.Auth.Abstractions;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Scheduler.Models;
@@ -19,10 +20,12 @@ public static class GraphJobEndpointExtensions
group.MapPost("/build", CreateGraphBuildJob)
.WithName("CreateGraphBuildJob")
.WithDescription("Enqueues a graph build job to construct the reachability graph for the specified tenant scope. Returns 201 Created with the new job ID. Requires graph.write scope.");
.WithDescription("Enqueues a graph build job to construct the reachability graph for the specified tenant scope. Returns 201 Created with the new job ID. Requires graph.write scope.")
.Audited("scheduler", "create_graph_build", "graph_job");
group.MapPost("/overlays", CreateGraphOverlayJob)
.WithName("CreateGraphOverlayJob")
.WithDescription("Enqueues a graph overlay job to apply incremental VEX or policy updates onto an existing reachability graph. Returns 201 Created with the new job ID. Requires graph.write scope.");
.WithDescription("Enqueues a graph overlay job to apply incremental VEX or policy updates onto an existing reachability graph. Returns 201 Created with the new job ID. Requires graph.write scope.")
.Audited("scheduler", "create_graph_overlay", "graph_job");
group.MapGet("/jobs", GetGraphJobs)
.WithName("GetGraphJobs")
.WithDescription("Lists graph jobs for the tenant with optional filters by status and job type. Returns a paginated collection ordered by creation time. Requires graph.read scope.");

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using StellaOps.Audit.Emission;
using StellaOps.Auth.Abstractions;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Scheduler.Models;
@@ -31,7 +32,8 @@ internal static class PolicyRunEndpointExtensions
group.MapPost("/", CreatePolicyRunAsync)
.WithName("CreatePolicyRun")
.WithDescription("Enqueues a new policy evaluation run for the specified policy ID and version. Returns 201 Created with the run ID and initial queued status. Requires policy.run scope.")
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "create_policy_run", "policy_run");
}
internal static async Task<IResult> ListPolicyRunsAsync(

View File

@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using StellaOps.Audit.Emission;
using StellaOps.Auth.Abstractions;
using StellaOps.Localization;
using StellaOps.Auth.ServerIntegration;
@@ -332,6 +333,7 @@ else
builder.Services.AddStellaOpsTenantServices();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddAuditEmission(builder.Configuration);
builder.Services.AddStellaOpsLocalization(builder.Configuration);
builder.Services.AddTranslationBundle(System.Reflection.Assembly.GetExecutingAssembly());

View File

@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Primitives;
using static StellaOps.Localization.T;
using StellaOps.Audit.Emission;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Scheduler.ImpactIndex;
using StellaOps.Scheduler.Models;
@@ -52,15 +53,18 @@ internal static class RunEndpoints
group.MapPost("/", CreateRunAsync)
.WithName("CreateSchedulerRun")
.WithDescription(_t("scheduler.run.create_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "create_run", "run");
group.MapPost("/{runId}/cancel", CancelRunAsync)
.WithName("CancelSchedulerRun")
.WithDescription(_t("scheduler.run.cancel_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "cancel_run", "run");
group.MapPost("/{runId}/retry", RetryRunAsync)
.WithName("RetrySchedulerRun")
.WithDescription(_t("scheduler.run.retry_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "retry_run", "run");
group.MapPost("/preview", PreviewImpactAsync)
.WithName("PreviewRunImpact")
.WithDescription(_t("scheduler.run.preview_description"))

View File

@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using static StellaOps.Localization.T;
using StellaOps.Audit.Emission;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Scheduler.Models;
using StellaOps.Scheduler.Persistence.Postgres.Repositories;
@@ -36,23 +37,28 @@ internal static class ScheduleEndpoints
group.MapPost("/", CreateScheduleAsync)
.WithName("CreateSchedule")
.WithDescription(_t("scheduler.schedule.create_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "create_schedule", "schedule");
group.MapPatch("/{scheduleId}", UpdateScheduleAsync)
.WithName("UpdateSchedule")
.WithDescription(_t("scheduler.schedule.update_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "update_schedule", "schedule");
group.MapDelete("/{scheduleId}", DeleteScheduleAsync)
.WithName("DeleteSchedule")
.WithDescription("Soft-deletes a schedule. System-managed schedules cannot be deleted.")
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "delete_schedule", "schedule");
group.MapPost("/{scheduleId}/pause", PauseScheduleAsync)
.WithName("PauseSchedule")
.WithDescription(_t("scheduler.schedule.pause_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "pause_schedule", "schedule");
group.MapPost("/{scheduleId}/resume", ResumeScheduleAsync)
.WithName("ResumeSchedule")
.WithDescription(_t("scheduler.schedule.resume_description"))
.RequireAuthorization(SchedulerPolicies.Operate);
.RequireAuthorization(SchedulerPolicies.Operate)
.Audited("scheduler", "resume_schedule", "schedule");
return routes;
}

View File

@@ -26,6 +26,7 @@
<ProjectReference Include="../../Router/__Libraries/StellaOps.Messaging/StellaOps.Messaging.csproj" />
<ProjectReference Include="../../Router/__Libraries/StellaOps.Router.AspNet/StellaOps.Router.AspNet.csproj" />
<ProjectReference Include="../../__Libraries/StellaOps.Localization/StellaOps.Localization.csproj" />
<ProjectReference Include="../../__Libraries/StellaOps.Audit.Emission/StellaOps.Audit.Emission.csproj" />
<ProjectReference Include="../../ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Scripts/StellaOps.ReleaseOrchestrator.Scripts.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -60,7 +60,7 @@ public sealed class ScanJobPlugin : ISchedulerJobPlugin
{
// Scan jobs use the standard Mode/Selector fields, not PluginConfig.
// Any PluginConfig on a scan schedule is ignored but valid.
return Task.FromResult(JobConfigValidationResult.Success);
return Task.FromResult(JobConfigValidationResult.Valid);
}
/// <inheritdoc />