fix(management): honor MgmtDeployArtifactsCommand.SiteId + enforce site scope (arch-review C2)

Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
Joseph Doherty
2026-07-10 05:51:03 -04:00
parent 5b00c049f8
commit 83e09fc210
6 changed files with 117 additions and 8 deletions
@@ -433,7 +433,7 @@ public class ManagementActor : ReceiveActor
DeleteScopeRuleCommand cmd => await HandleDeleteScopeRule(sp, cmd, user.Username),
// Deployments
MgmtDeployArtifactsCommand cmd => await HandleDeployArtifacts(sp, cmd, user.Username),
MgmtDeployArtifactsCommand cmd => await HandleDeployArtifacts(sp, cmd, user),
QueryDeploymentsCommand cmd => await HandleQueryDeployments(sp, cmd, user),
GetDeploymentDiffCommand cmd => await HandleGetDeploymentDiff(sp, cmd, user),
@@ -2205,10 +2205,24 @@ public class ManagementActor : ReceiveActor
// Deployment handlers
// ========================================================================
private static async Task<object?> HandleDeployArtifacts(IServiceProvider sp, MgmtDeployArtifactsCommand cmd, string user)
private static async Task<object?> HandleDeployArtifacts(IServiceProvider sp, MgmtDeployArtifactsCommand cmd, AuthenticatedUser user)
{
// A site-scoped Deployer may not trigger a FLEET-WIDE artifact deployment:
// EnforceSiteScope(null) is a no-op by design, so the fleet-wide case needs
// its own guard (arch-review C2 authorization gap).
if (cmd.SiteId is null
&& user.PermittedSiteIds.Length > 0
&& !user.Roles.Contains(Roles.Administrator, StringComparer.OrdinalIgnoreCase))
{
throw new SiteScopeViolationException(
"Site-scoped users cannot deploy artifacts fleet-wide; specify a target site id.");
}
EnforceSiteScope(user, cmd.SiteId);
var svc = sp.GetRequiredService<ArtifactDeploymentService>();
var result = await svc.DeployToAllSitesAsync(user);
var result = cmd.SiteId is int siteId
? await svc.DeployToSiteAsync(siteId, user.Username)
: await svc.DeployToAllSitesAsync(user.Username);
return result.IsSuccess
? result.Value
: throw new ManagementCommandException(result.Error);