From 0fd8ca22d1445b38161d7d39ca4fffde27973c44 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Mon, 23 Mar 2026 06:28:59 +0100 Subject: [PATCH] renaming global admin --- docs/architecture.md | 26 ++-- .../AutopilotMonitor.Agent/buildcounter.txt | 2 +- .../EndpointPolicyCatalogCompletenessTests.cs | 2 +- ...utopilotDeviceValidationConsentFunction.cs | 12 +- .../Functions/Admin/DeviceBlockFunction.cs | 10 +- .../Admin/GetAllBlockedDevicesFunction.cs | 8 +- .../Admin/GetGlobalAuditLogsFunction.cs | 18 +-- .../Admin/ReseedFromGitHubFunction.cs | 4 +- .../Admin/TenantAdminManagementFunction.cs | 74 +++++------ .../Functions/Admin/TenantOffboardFunction.cs | 14 +- .../Admin/TriggerMaintenanceFunction.cs | 8 +- .../Functions/Admin/VersionBlockFunction.cs | 10 +- .../CreateBootstrapSessionFunction.cs | 12 +- .../ListBootstrapSessionsFunction.cs | 12 +- .../RevokeBootstrapSessionFunction.cs | 12 +- .../Config/GetAdminConfigurationFunction.cs | 4 +- .../GetAllTenantConfigurationsFunction.cs | 4 +- .../Config/GetTenantConfigurationFunction.cs | 12 +- .../UpdateAdminConfigurationFunction.cs | 4 +- .../UpdateTenantConfigurationFunction.cs | 16 +-- .../DiagnosticsDownloadFunction.cs | 10 +- .../Functions/Feedback/FeedbackFunction.cs | 2 +- .../Global/GlobalNotificationsFunction.cs | 36 +++--- .../Functions/Infrastructure/AuthFunction.cs | 94 +++++++------- .../Infrastructure/HealthCheckFunction.cs | 4 +- .../SignalRAddToGroupFunction.cs | 32 ++--- .../SignalRRemoveFromGroupFunction.cs | 32 ++--- .../Metrics/GetGlobalAppMetricsFunction.cs | 18 +-- ...lobalGeographicLocationSessionsFunction.cs | 18 +-- .../GetGlobalGeographicMetricsFunction.cs | 18 +-- .../GetGlobalPlatformMetricsFunction.cs | 16 +-- .../Metrics/PlatformUsageMetricsFunction.cs | 10 +- .../Progress/ProgressPortalFunction.cs | 16 +-- .../GetSessionReportDownloadUrlFunction.cs | 6 +- .../Reports/GetSessionReportsFunction.cs | 4 +- .../Reports/SubmitSessionReportFunction.cs | 22 ++-- .../UpdateSessionReportNoteFunction.cs | 6 +- .../Functions/Rules/GetRuleResultsFunction.cs | 16 +-- .../Functions/Rules/GlobalRulesFunction.cs | 32 ++--- .../Functions/Rules/ImeLogPatternsFunction.cs | 8 +- .../Rules/PreviewWhitelistFunction.cs | 14 +- .../Sessions/GetAllSessionsFunction.cs | 6 +- .../Sessions/GetSessionEventsFunction.cs | 14 +- .../Functions/Sessions/GetSessionFunction.cs | 10 +- .../Sessions/MarkSessionFailedFunction.cs | 4 +- .../Sessions/RegisterSessionFunction.cs | 12 +- .../Vulnerability/GetCpeMappingsFunction.cs | 2 +- .../GetSoftwareInventoryFunction.cs | 10 +- .../GetUnmatchedSoftwareFunction.cs | 8 +- .../GetVulnerabilityReportFunction.cs | 16 +-- .../SaveCustomCpeMappingFunction.cs | 2 +- .../TriggerVulnerabilityDataSyncFunction.cs | 8 +- .../Helpers/SignalRGroupHelper.cs | 2 +- .../Middleware/PolicyEnforcementMiddleware.cs | 30 ++--- .../AutopilotMonitor.Functions/Program.cs | 4 +- .../Security/EndpointAccessPolicyCatalog.cs | 98 +++++++------- .../Security/SecurityValidator.cs | 2 +- ...cAdminService.cs => GlobalAdminService.cs} | 104 +++++++-------- ...ervice.cs => GlobalNotificationService.cs} | 60 ++++----- .../Services/ImeLogPatternService.cs | 4 +- .../Services/PreviewWhitelistService.cs | 2 +- .../TableStorageService.Maintenance.cs | 2 +- .../Services/TableStorageService.Metrics.cs | 4 +- .../Services/TableStorageService.Sessions.cs | 6 +- .../Services/TenantConfigurationService.cs | 2 +- .../AutopilotMonitor.Shared/Constants.cs | 10 +- .../Models/Config/AdminConfiguration.cs | 4 +- .../Models/Config/TenantConfiguration.cs | 8 +- .../Models/Diagnostics/DiagnosticsLogPath.cs | 4 +- .../app/admin/AdminConfigContext.tsx | 10 +- .../app/admin/AdminPageSections.tsx | 2 +- .../components/AdminConfigSettingsSection.tsx | 2 +- .../admin/components/DeviceBlockSection.tsx | 2 +- .../components/SessionReportsSection.tsx | 6 +- .../components/TenantManagementSection.tsx | 2 +- .../app/admin/layout.tsx | 6 +- .../metrics/sections/SectionAgentMetrics.tsx | 4 +- .../metrics/sections/SectionPlatformUsage.tsx | 4 +- .../sections/SectionTenantConfigReport.tsx | 6 +- .../app/analyze-rules/page.tsx | 32 ++--- .../autopilot-monitor-web/app/audit/page.tsx | 14 +- .../app/dashboard/components/SessionTable.tsx | 28 ++-- .../app/dashboard/components/SettingsMenu.tsx | 26 ++-- .../app/dashboard/page.tsx | 120 +++++++++--------- .../app/diagnosis/[sessionId]/page.tsx | 12 +- .../app/docs/sections/SectionSettings.tsx | 2 +- .../app/fleet-health/page.tsx | 20 +-- .../app/gather-rules/page.tsx | 38 +++--- .../app/geographic-performance/page.tsx | 20 +-- .../geographic-performance/sessions/page.tsx | 18 +-- .../components/ImePatternCard.tsx | 4 +- .../app/ime-log-patterns/page.tsx | 24 ++-- src/Web/autopilot-monitor-web/app/layout.tsx | 6 +- .../app/preview/page.tsx | 2 +- .../app/privacy/page.tsx | 2 +- .../[sessionId]/components/EventTimeline.tsx | 2 +- .../app/sessions/[sessionId]/page.tsx | 24 ++-- .../app/settings/SettingsPageSections.tsx | 2 +- .../app/settings/TenantConfigContext.tsx | 10 +- .../components/DataManagementSection.tsx | 8 +- .../app/settings/layout.tsx | 8 +- .../sections/SectionDataManagement.tsx | 2 +- .../app/settings/page.tsx | 4 +- .../app/usage-metrics/page.tsx | 32 ++--- .../app/usage-metrics/page.tsx.bak | 2 +- .../components/AppInsightsInit.tsx | 2 +- .../components/GlobalSidebar.tsx | 44 +++---- .../components/Navbar.tsx | 50 ++++---- .../components/ProtectedRoute.tsx | 14 +- .../components/landing/AuthGate.tsx | 2 +- .../contexts/AuthContext.tsx | 10 +- .../contexts/GlobalNotificationContext.tsx | 44 +++---- .../autopilot-monitor-web/lib/appInsights.ts | 8 +- .../lib/globalNavConfig.tsx | 16 +-- .../tsconfig.tsbuildinfo | 2 +- tasks/todo.md | 8 +- 116 files changed, 911 insertions(+), 911 deletions(-) rename src/Backend/AutopilotMonitor.Functions/Services/{GalacticAdminService.cs => GlobalAdminService.cs} (60%) rename src/Backend/AutopilotMonitor.Functions/Services/{GalacticNotificationService.cs => GlobalNotificationService.cs} (72%) diff --git a/docs/architecture.md b/docs/architecture.md index e3d1ab6e..96047ce5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -247,12 +247,12 @@ Monitoring/ | **Sessions** | `GET /sessions`, `GET /sessions/{id}`, `GET /sessions/{id}/events`, `POST /sessions/{id}/analysis`, `DELETE /sessions/{id}`, `POST /sessions/{id}/mark-failed` | | **Rules** | CRUD for `/rules/gather`, `/rules/analyze`, `/rules/ime-log-patterns`, `POST /rules/reseed-from-github` | | **Config** | `GET/POST /global/config`, `GET/PUT /config/{tenantId}` | -| **Auth** | `GET /auth/me`, `GET /auth/is-galactic-admin`, CRUD `/auth/galactic-admins` | +| **Auth** | `GET /auth/me`, `GET /auth/is-global-admin`, CRUD `/auth/global-admins` | | **Tenants** | CRUD `/tenants/{id}/admins`, `POST /tenants/{id}/offboard` | | **Devices** | `POST /devices/block`, `DELETE /devices/block/{serial}`, `GET /devices/blocked` | -| **Reports** | `POST /sessions/{id}/report`, `GET /galactic/session-reports` | +| **Reports** | `POST /sessions/{id}/report`, `GET /global/session-reports` | | **Metrics** | `GET /metrics/usage`, `GET /metrics/app`, `GET /metrics/geographic`, `GET /stats/platform` | -| **Galactic** | `/galactic/metrics/*`, `/galactic/audit/logs`, `/galactic/session-reports`, `/galactic/notifications` (CRUD + dismiss) | +| **Global** | `/global/metrics/*`, `/global/audit/logs`, `/global/session-reports`, `/global/notifications` (CRUD + dismiss) | | **Progress** | `GET /progress/sessions`, `GET /progress/sessions/{id}/events` | | **SignalR** | `POST /realtime/negotiate`, `POST /realtime/groups/join`, `POST /realtime/groups/leave` | | **Health** | `GET /health`, `GET /health/detailed` | @@ -276,7 +276,7 @@ Monitoring/ | `SessionReportService` | Report ZIP generation + Blob upload | | `GraphTokenService` | MS Graph token acquisition for Autopilot device validation | | `BlockedVersionService` | Version-based block/kill rules with wildcard and ceiling patterns | -| `GalacticNotificationService` | Persistent in-app notifications for Galactic Admins (survives page reloads) | +| `GlobalNotificationService` | Persistent in-app notifications for Global Admins (survives page reloads) | | `HealthCheckService` | Health checks for Storage, Processing, and Agent binary availability | | `PreviewWhitelistService` | Private Preview tenant whitelist with 5-min cache | | `ResendEmailService` | Transactional emails via Resend.com for Preview notifications | @@ -339,16 +339,16 @@ Agent POST /api/agent/ingest (NDJSON+gzip) | `/sessions/[sessionId]` | Session detail, event timeline, analysis | Yes | Any | | `/diagnosis/[sessionId]` | Rule analysis results | Yes | Any | | `/settings` | Tenant configuration (10+ sections) | Yes | Tenant Admin | -| `/admin-configuration` | Global admin settings | Yes | Galactic Admin | +| `/admin-configuration` | Global admin settings | Yes | Global Admin | | `/gather-rules` | Gather rule CRUD | Yes | Tenant Admin | | `/analyze-rules` | Analyze rule CRUD | Yes | Tenant Admin | | `/ime-log-patterns` | IME pattern management | Yes | Tenant Admin | | `/fleet-health` | App metrics, fleet analytics | Yes | Tenant Admin | | `/usage-metrics` | Tenant usage analytics | Yes | Tenant Admin | -| `/platform-metrics` | Platform-wide metrics | Yes | Galactic Admin | +| `/platform-metrics` | Platform-wide metrics | Yes | Global Admin | | `/audit` | Audit log viewer | Yes | Tenant Admin | -| `/health-check` | Backend health status | Yes | Galactic Admin | -| `/geographic-performance` | Geo map of deployments | Yes | Galactic Admin | +| `/health-check` | Backend health status | Yes | Global Admin | +| `/geographic-performance` | Geo map of deployments | Yes | Global Admin | | `/progress` | Real-time enrollment progress tracking | Yes | Tenant Admin | | `/preview` | Private Preview waitlist/approval page | Yes | Unapproved tenants | | `/changelog` | Platform change log & known issues | Public | — | @@ -365,7 +365,7 @@ React Context API (no Redux/Zustand): | Context | Purpose | |---------|---------| -| `AuthContext` | MSAL + user info + role detection (galactic/tenant admin) | +| `AuthContext` | MSAL + user info + role detection (global/tenant admin) | | `SignalRContext` | WebSocket connection, group subscriptions, auto-reconnect | | `TenantContext` | Current tenant ID (persisted to localStorage) | | `NotificationContext` | Toast notifications with auto-dismiss + deduplication | @@ -443,14 +443,14 @@ React Context API (no Redux/Zustand): | `BootstrapSessions` | TenantId / "CodeLookup" | ShortCode | OOBE bootstrap tokens | | `BlockedDevices` | TenantId | SerialNumber | Blocked devices | | `SessionReports` | TenantId | ReportId | User-submitted reports | -| `GalacticAdmins` | "GalacticAdmins" | UPN | Platform-level admins | +| `GlobalAdmins` | "GlobalAdmins" | UPN | Platform-level admins | | `TenantAdmins` | TenantId | UPN | Tenant-level admins | | `PreviewWhitelist` | "Preview" | TenantId | Preview access gate | | `UserActivity` | TenantId | UserId | User login tracking | | `RuleStates` | TenantId | RuleId | Rule enable/disable state | | `PreviewConfig` | "Preview" | "config" | Preview feature config | | `BlockedVersions` | "BlockedVersions" | Pattern | Version block/kill rules (wildcards, ceilings) | -| `GalacticNotifications` | "GalacticNotifications" | InvertedTicks_Id | Persistent in-app notifications for Galactic Admins | +| `GlobalNotifications` | "GlobalNotifications" | InvertedTicks_Id | Persistent in-app notifications for Global Admins | ### Azure Blob Storage @@ -521,7 +521,7 @@ ValidateSecurityAsync() (SecurityValidationExtensions.cs) | Role | Scope | Capabilities | |------|-------|-------------| -| **Galactic Admin** | Platform-wide | Global config, all tenants, platform metrics, health checks | +| **Global Admin** | Platform-wide | Global config, all tenants, platform metrics, health checks | | **Tenant Admin** | Single tenant | Tenant config, rules, admin management, device blocking | | **User** | Single tenant | Read-only dashboard, session detail view | @@ -540,7 +540,7 @@ ValidateSecurityAsync() (SecurityValidationExtensions.cs) | Group | Events | Triggered By | |-------|--------|-------------| | `tenant-{tenantId}` | `newSession`, `sessionStatusChanged`, `eventReceived`, `ruleResultReceived` | Event ingestion, session registration | -| `galactic-admins` | `newSession` (all tenants), platform stats updates | Cross-tenant broadcasts | +| `global-admins` | `newSession` (all tenants), platform stats updates | Cross-tenant broadcasts | ### Client-Side (SignalRContext) diff --git a/src/Agent/AutopilotMonitor.Agent/buildcounter.txt b/src/Agent/AutopilotMonitor.Agent/buildcounter.txt index 5fffd3d0..69629048 100644 --- a/src/Agent/AutopilotMonitor.Agent/buildcounter.txt +++ b/src/Agent/AutopilotMonitor.Agent/buildcounter.txt @@ -1 +1 @@ -568 +569 diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs index bc7f3288..5deb93a3 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs @@ -138,7 +138,7 @@ public class EndpointPolicyCatalogCompletenessTests [InlineData("PATCH", "/api/tenants/tid-1/admins/user@contoso.com/permissions", "tenants/{tenantId}/admins/{adminUpn}/permissions")] [InlineData("DELETE", "/api/devices/block/SN123456", "devices/block/{encodedSerialNumber}")] [InlineData("DELETE", "/api/versions/block/v1.0.*", "versions/block/{encodedPattern}")] - [InlineData("PATCH", "/api/galactic/session-reports/report-1/note", "galactic/session-reports/{reportId}/note")] + [InlineData("PATCH", "/api/global/session-reports/report-1/note", "global/session-reports/{reportId}/note")] public void ParameterizedRoutes_MatchCorrectly(string httpMethod, string requestPath, string expectedTemplate) { var entry = EndpointAccessPolicyCatalog.FindPolicy(httpMethod, requestPath); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/AutopilotDeviceValidationConsentFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/AutopilotDeviceValidationConsentFunction.cs index b12c8098..17fa1924 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/AutopilotDeviceValidationConsentFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/AutopilotDeviceValidationConsentFunction.cs @@ -14,20 +14,20 @@ public class AutopilotDeviceValidationConsentFunction private readonly ILogger _logger; private readonly IConfiguration _configuration; private readonly TenantAdminsService _tenantAdminsService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly GraphTokenService _graphTokenService; public AutopilotDeviceValidationConsentFunction( ILogger logger, IConfiguration configuration, TenantAdminsService tenantAdminsService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, GraphTokenService graphTokenService) { _logger = logger; _configuration = configuration; _tenantAdminsService = tenantAdminsService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _graphTokenService = graphTokenService; } @@ -108,10 +108,10 @@ public class AutopilotDeviceValidationConsentFunction return forbidden; } - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); var isTenantAdmin = await _tenantAdminsService.IsTenantAdminAsync(tenantId, userIdentifier); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning( "User {User} attempted autopilot-device-validation consent operation without admin rights for tenant {TenantId}", @@ -121,7 +121,7 @@ public class AutopilotDeviceValidationConsentFunction var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { - error = "Access denied. Tenant Admin or Galactic Admin required." + error = "Access denied. Tenant Admin or Global Admin required." }); return forbidden; } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/DeviceBlockFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/DeviceBlockFunction.cs index 4a0fbc22..831e1eae 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/DeviceBlockFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/DeviceBlockFunction.cs @@ -34,7 +34,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var tenantId = req.Query["tenantId"]; if (string.IsNullOrEmpty(tenantId)) @@ -62,7 +62,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); string body; @@ -110,7 +110,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin var isKill = action == "Kill"; _logger.LogWarning( - "Galactic Admin {User} {Action} device {SerialNumber} in tenant {TenantId} for {Hours}h. Reason: {Reason}", + "Global Admin {User} {Action} device {SerialNumber} in tenant {TenantId} for {Hours}h. Reason: {Reason}", userIdentifier, isKill ? "issued KILL signal to" : "blocked", serialNumber, tenantId, durationHours, reason); var response = req.CreateResponse(HttpStatusCode.OK); @@ -142,7 +142,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); var tenantId = req.Query["tenantId"]; @@ -164,7 +164,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin ); _logger.LogInformation( - "Galactic Admin {User} unblocked device {SerialNumber} in tenant {TenantId}", + "Global Admin {User} unblocked device {SerialNumber} in tenant {TenantId}", userIdentifier, serialNumber, tenantId); var response = req.CreateResponse(HttpStatusCode.OK); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetAllBlockedDevicesFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetAllBlockedDevicesFunction.cs index 0dcb1f02..6b0a0bc7 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetAllBlockedDevicesFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetAllBlockedDevicesFunction.cs @@ -21,16 +21,16 @@ namespace AutopilotMonitor.Functions.Functions.Admin _blockedDeviceService = blockedDeviceService; } - /// GET /api/galactic/devices/blocked — list all active blocks across all tenants + /// GET /api/global/devices/blocked — list all active blocks across all tenants [Function("GetAllBlockedDevices")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/devices/blocked")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/devices/blocked")] HttpRequestData req) { - _logger.LogInformation("GetAllBlockedDevices function processing request (Galactic Admin Mode)"); + _logger.LogInformation("GetAllBlockedDevices function processing request (Global Admin Mode)"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var blocked = await _blockedDeviceService.GetAllBlockedDevicesAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetGlobalAuditLogsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetGlobalAuditLogsFunction.cs index 47b02b8d..bd2b4455 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetGlobalAuditLogsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/GetGlobalAuditLogsFunction.cs @@ -7,28 +7,28 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Admin { - public class GetGalacticAuditLogsFunction + public class GetGlobalAuditLogsFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TableStorageService _storageService; - public GetGalacticAuditLogsFunction( - ILogger logger, + public GetGlobalAuditLogsFunction( + ILogger logger, TableStorageService storageService) { _logger = logger; _storageService = storageService; } - [Function("GetGalacticAuditLogs")] + [Function("GetGlobalAuditLogs")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/audit/logs")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/audit/logs")] HttpRequestData req) { - _logger.LogInformation("GetGalacticAuditLogs function processing request (Galactic Admin Mode)"); + _logger.LogInformation("GetGlobalAuditLogs function processing request (Global Admin Mode)"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); _logger.LogInformation($"Fetching all audit logs across all tenants (User: {userEmail})"); @@ -47,7 +47,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin } catch (Exception ex) { - _logger.LogError(ex, "Error getting galactic audit logs"); + _logger.LogError(ex, "Error getting global audit logs"); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteAsJsonAsync(new diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/ReseedFromGitHubFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/ReseedFromGitHubFunction.cs index 5c1a1f6e..c539013f 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/ReseedFromGitHubFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/ReseedFromGitHubFunction.cs @@ -45,7 +45,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var upn = TenantHelper.GetUserIdentifier(req); // Parse ?type= parameter (default: all) @@ -58,7 +58,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin typeParam = (typeEnd > 0 ? queryString.Substring(typeStart, typeEnd - typeStart) : queryString.Substring(typeStart)).ToLowerInvariant(); } - _logger.LogInformation($"Reseed from GitHub triggered by Galactic Admin {upn}, type={typeParam}"); + _logger.LogInformation($"Reseed from GitHub triggered by Global Admin {upn}, type={typeParam}"); var gatherResult = new { deleted = 0, written = 0 }; var analyzeResult = new { deleted = 0, written = 0 }; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantAdminManagementFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantAdminManagementFunction.cs index 7a43471d..de97a1f8 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantAdminManagementFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantAdminManagementFunction.cs @@ -11,31 +11,31 @@ namespace AutopilotMonitor.Functions.Functions.Admin; /// /// Tenant Admin Management endpoints -/// Allows tenant admins and galactic admins to manage admin users for a tenant +/// Allows tenant admins and global admins to manage admin users for a tenant /// public class TenantAdminManagementFunction { private readonly ILogger _logger; private readonly TenantAdminsService _tenantAdminsService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TableStorageService _storageService; public TenantAdminManagementFunction( ILogger logger, TenantAdminsService tenantAdminsService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TableStorageService storageService) { _logger = logger; _tenantAdminsService = tenantAdminsService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _storageService = storageService; } /// /// GET /api/tenants/{tenantId}/admins /// Gets all admins for a tenant - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// [Function("GetTenantAdmins")] [Authorize] @@ -50,16 +50,16 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to access admins for tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } @@ -75,7 +75,7 @@ public class TenantAdminManagementFunction /// /// POST /api/tenants/{tenantId}/admins /// Adds a new admin to a tenant - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// [Function("AddTenantAdmin")] [Authorize] @@ -90,16 +90,16 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to add admin to tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } @@ -139,7 +139,7 @@ public class TenantAdminManagementFunction /// /// DELETE /api/tenants/{tenantId}/admins/{adminUpn} /// Removes an admin from a tenant - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// Note: Cannot remove yourself if you're the last admin /// [Function("RemoveTenantAdmin")] @@ -156,24 +156,24 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to remove admin from tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } // Check if trying to remove self if (adminUpn.Equals(upn, StringComparison.OrdinalIgnoreCase)) { - // Check if this is the last Admin-role member (only for non-Galactic-Admins) - if (!isGalacticAdmin) + // Check if this is the last Admin-role member (only for non-Global-Admins) + if (!isGlobalAdmin) { var members = await _tenantAdminsService.GetTenantAdminsAsync(tenantId); var adminCount = members.Count(m => m.IsEnabled && (m.Role == null || m.Role == AutopilotMonitor.Shared.Constants.TenantRoles.Admin)); @@ -207,7 +207,7 @@ public class TenantAdminManagementFunction /// /// PATCH /api/tenants/{tenantId}/admins/{adminUpn}/disable /// Disables an admin for a tenant - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// [Function("DisableTenantAdmin")] [Authorize] @@ -223,16 +223,16 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to disable admin for tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } @@ -258,7 +258,7 @@ public class TenantAdminManagementFunction /// /// PATCH /api/tenants/{tenantId}/admins/{adminUpn}/enable /// Enables an admin for a tenant - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// [Function("EnableTenantAdmin")] [Authorize] @@ -274,16 +274,16 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to enable admin for tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } @@ -308,7 +308,7 @@ public class TenantAdminManagementFunction /// /// PATCH /api/tenants/{tenantId}/admins/{adminUpn}/permissions /// Updates role and permissions for a tenant member - /// Accessible by: Galactic Admins OR Tenant Admins of the same tenant + /// Accessible by: Global Admins OR Tenant Admins of the same tenant /// [Function("UpdateMemberPermissions")] [Authorize] @@ -324,16 +324,16 @@ public class TenantAdminManagementFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Check authorization: either Galactic Admin OR Tenant Admin of the same tenant - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check authorization: either Global Admin OR Tenant Admin of the same tenant + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning("User {Upn} attempted to update member permissions for tenant {TenantId} without authorization", upn, tenantId); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Galactic Admin or a Tenant Admin for this tenant." }); + await forbiddenResponse.WriteAsJsonAsync(new { error = "Access denied. You must be a Global Admin or a Tenant Admin for this tenant." }); return forbiddenResponse; } @@ -348,7 +348,7 @@ public class TenantAdminManagementFunction // Prevent demoting yourself if you're the last Admin if (adminUpn.Equals(upn, StringComparison.OrdinalIgnoreCase) && body.Role != AutopilotMonitor.Shared.Constants.TenantRoles.Admin) { - if (!isGalacticAdmin) + if (!isGlobalAdmin) { var members = await _tenantAdminsService.GetTenantAdminsAsync(tenantId); var adminCount = members.Count(m => m.IsEnabled && (m.Role == null || m.Role == AutopilotMonitor.Shared.Constants.TenantRoles.Admin)); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantOffboardFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantOffboardFunction.cs index 42c78f62..31ccb132 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantOffboardFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TenantOffboardFunction.cs @@ -22,18 +22,18 @@ public class TenantOffboardFunction { private readonly ILogger _logger; private readonly TenantAdminsService _tenantAdminsService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TableServiceClient _tableServiceClient; public TenantOffboardFunction( ILogger logger, TenantAdminsService tenantAdminsService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, IConfiguration configuration) { _logger = logger; _tenantAdminsService = tenantAdminsService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; var connectionString = configuration["AzureTableStorageConnectionString"]; _tableServiceClient = new TableServiceClient(connectionString); } @@ -41,7 +41,7 @@ public class TenantOffboardFunction /// /// DELETE /api/tenants/{tenantId}/offboard /// Permanently deletes ALL data for a tenant across all tables. - /// Accessible by: Tenant Admins of the same tenant OR Galactic Admins. + /// Accessible by: Tenant Admins of the same tenant OR Global Admins. /// This action is IRREVERSIBLE. /// [Function("OffboardTenant")] @@ -57,12 +57,12 @@ public class TenantOffboardFunction var userTenantId = principal.GetTenantId(); var upn = principal.GetUserPrincipalName(); - // Only Tenant Admins of the same tenant OR Galactic Admins may offboard - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Only Tenant Admins of the same tenant OR Global Admins may offboard + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var isTenantAdmin = tenantId.Equals(userTenantId, StringComparison.OrdinalIgnoreCase) && await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn); - if (!isGalacticAdmin && !isTenantAdmin) + if (!isGlobalAdmin && !isTenantAdmin) { _logger.LogWarning($"User {upn} attempted to offboard tenant {tenantId} without authorization"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TriggerMaintenanceFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TriggerMaintenanceFunction.cs index 06c3152e..3778cb3d 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TriggerMaintenanceFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/TriggerMaintenanceFunction.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Admin { /// - /// Allows Galactic Admins to manually trigger maintenance tasks + /// Allows Global Admins to manually trigger maintenance tasks /// public class TriggerMaintenanceFunction { @@ -27,7 +27,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin /// /// POST /api/maintenance/trigger - /// Manually trigger maintenance tasks (Galactic Admin only) + /// Manually trigger maintenance tasks (Global Admin only) /// Query parameters: /// - date: Optional date to aggregate (yyyy-MM-dd). If not provided, uses yesterday. /// - aggregateOnly: If true, only runs aggregation (skips timeout and cleanup) @@ -39,10 +39,10 @@ namespace AutopilotMonitor.Functions.Functions.Admin { _logger.LogInformation("Manual maintenance trigger requested"); - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"Maintenance trigger initiated by Galactic Admin: {userEmail}"); + _logger.LogInformation($"Maintenance trigger initiated by Global Admin: {userEmail}"); try { diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/VersionBlockFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/VersionBlockFunction.cs index 50fc9a9d..396a55ed 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Admin/VersionBlockFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Admin/VersionBlockFunction.cs @@ -34,7 +34,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var rules = await _blockedVersionService.GetBlockedVersionsAsync(); @@ -58,7 +58,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); string body; @@ -105,7 +105,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin ); _logger.LogWarning( - "Galactic Admin {User} added version {Action} rule: Pattern={Pattern}, Reason={Reason}", + "Global Admin {User} added version {Action} rule: Pattern={Pattern}, Reason={Reason}", userIdentifier, normalizedAction, versionPattern, reason); var response = req.CreateResponse(HttpStatusCode.OK); @@ -135,7 +135,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); var versionPattern = Uri.UnescapeDataString(encodedPattern ?? string.Empty); @@ -153,7 +153,7 @@ namespace AutopilotMonitor.Functions.Functions.Admin ); _logger.LogInformation( - "Galactic Admin {User} removed version block rule: Pattern={Pattern}", + "Global Admin {User} removed version block rule: Pattern={Pattern}", userIdentifier, versionPattern); var response = req.CreateResponse(HttpStatusCode.OK); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/CreateBootstrapSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/CreateBootstrapSessionFunction.cs index fb8b067f..51967420 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/CreateBootstrapSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/CreateBootstrapSessionFunction.cs @@ -20,20 +20,20 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap { private readonly ILogger _logger; private readonly BootstrapSessionService _bootstrapService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TenantConfigurationService _configService; private readonly TableStorageService _storageService; public CreateBootstrapSessionFunction( ILogger logger, BootstrapSessionService bootstrapService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TenantConfigurationService configService, TableStorageService storageService) { _logger = logger; _bootstrapService = bootstrapService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _configService = configService; _storageService = storageService; } @@ -64,11 +64,11 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap // Use tenant from JWT if not specified in body var tenantId = !string.IsNullOrEmpty(request.TenantId) ? request.TenantId : authenticatedTenantId; - // Cross-tenant boundary check — only Galactic Admins may operate on other tenants + // Cross-tenant boundary check — only Global Admins may operate on other tenants if (!string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) { - var isGalactic = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalactic) + var isGlobal = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobal) { var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { error = "Access denied: tenant mismatch" }); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/ListBootstrapSessionsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/ListBootstrapSessionsFunction.cs index 66fa5291..942d3112 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/ListBootstrapSessionsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/ListBootstrapSessionsFunction.cs @@ -19,18 +19,18 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap { private readonly ILogger _logger; private readonly BootstrapSessionService _bootstrapService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TenantConfigurationService _configService; public ListBootstrapSessionsFunction( ILogger logger, BootstrapSessionService bootstrapService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TenantConfigurationService configService) { _logger = logger; _bootstrapService = bootstrapService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _configService = configService; } @@ -46,11 +46,11 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap var tenantId = req.Query["tenantId"] ?? authenticatedTenantId; - // Cross-tenant boundary check — only Galactic Admins may operate on other tenants + // Cross-tenant boundary check — only Global Admins may operate on other tenants if (!string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) { - var isGalactic = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalactic) + var isGlobal = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobal) { var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { error = "Access denied: tenant mismatch" }); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/RevokeBootstrapSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/RevokeBootstrapSessionFunction.cs index 80283659..f7ffb179 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/RevokeBootstrapSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Bootstrap/RevokeBootstrapSessionFunction.cs @@ -17,20 +17,20 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap { private readonly ILogger _logger; private readonly BootstrapSessionService _bootstrapService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TenantConfigurationService _configService; private readonly TableStorageService _storageService; public RevokeBootstrapSessionFunction( ILogger logger, BootstrapSessionService bootstrapService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TenantConfigurationService configService, TableStorageService storageService) { _logger = logger; _bootstrapService = bootstrapService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _configService = configService; _storageService = storageService; } @@ -48,11 +48,11 @@ namespace AutopilotMonitor.Functions.Functions.Bootstrap var tenantId = req.Query["tenantId"] ?? authenticatedTenantId; - // Cross-tenant boundary check — only Galactic Admins may operate on other tenants + // Cross-tenant boundary check — only Global Admins may operate on other tenants if (!string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) { - var isGalactic = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalactic) + var isGlobal = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobal) { var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { error = "Access denied: tenant mismatch" }); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAdminConfigurationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAdminConfigurationFunction.cs index dfe4cbff..37096c34 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAdminConfigurationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAdminConfigurationFunction.cs @@ -28,10 +28,10 @@ namespace AutopilotMonitor.Functions.Functions.Config { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware string userIdentifier = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"GetAdminConfiguration by Galactic Admin user {userIdentifier}"); + _logger.LogInformation($"GetAdminConfiguration by Global Admin user {userIdentifier}"); var config = await _adminConfigService.GetConfigurationAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAllTenantConfigurationsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAllTenantConfigurationsFunction.cs index 0d355d35..bc839bd7 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAllTenantConfigurationsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetAllTenantConfigurationsFunction.cs @@ -28,10 +28,10 @@ namespace AutopilotMonitor.Functions.Functions.Config { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware string userIdentifier = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"GetAllTenantConfigurations by Galactic Admin {userIdentifier}"); + _logger.LogInformation($"GetAllTenantConfigurations by Global Admin {userIdentifier}"); var configurations = await _configService.GetAllConfigurationsAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetTenantConfigurationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetTenantConfigurationFunction.cs index 604ce5c1..46f0a4e4 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetTenantConfigurationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/GetTenantConfigurationFunction.cs @@ -13,16 +13,16 @@ namespace AutopilotMonitor.Functions.Functions.Config { private readonly ILogger _logger; private readonly TenantConfigurationService _configService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetTenantConfigurationFunction( ILogger logger, TenantConfigurationService configService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _configService = configService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetTenantConfiguration")] @@ -36,11 +36,11 @@ namespace AutopilotMonitor.Functions.Functions.Config string authenticatedTenantId = TenantHelper.GetTenantId(req); string userIdentifier = TenantHelper.GetUserIdentifier(req); - // Validate tenant access: cross-tenant only for Galactic Admins + // Validate tenant access: cross-tenant only for Global Admins if (!string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { _logger.LogWarning("User {User} from tenant {AuthTenant} attempted to access configuration for tenant {TargetTenant}", userIdentifier, authenticatedTenantId, tenantId); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs index c0430434..6f24fcdd 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateAdminConfigurationFunction.cs @@ -34,10 +34,10 @@ namespace AutopilotMonitor.Functions.Functions.Config { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware string userIdentifier = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"UpdateAdminConfiguration by Galactic Admin user {userIdentifier}"); + _logger.LogInformation($"UpdateAdminConfiguration by Global Admin user {userIdentifier}"); // Parse request body if (req.Headers.TryGetValues("Content-Length", out var clValues) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateTenantConfigurationFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateTenantConfigurationFunction.cs index 086184a7..ffa11c47 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateTenantConfigurationFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Config/UpdateTenantConfigurationFunction.cs @@ -16,18 +16,18 @@ namespace AutopilotMonitor.Functions.Functions.Config { private readonly ILogger _logger; private readonly TenantConfigurationService _configService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TableStorageService _storageService; public UpdateTenantConfigurationFunction( ILogger logger, TenantConfigurationService configService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TableStorageService storageService) { _logger = logger; _configService = configService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _storageService = storageService; } @@ -43,10 +43,10 @@ namespace AutopilotMonitor.Functions.Functions.Config string userIdentifier = TenantHelper.GetUserIdentifier(req); // GA check needed for: cross-tenant bypass + protected field filtering - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); - // Validate tenant access: cross-tenant only for Galactic Admins - if (!isGalacticAdmin && !string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) + // Validate tenant access: cross-tenant only for Global Admins + if (!isGlobalAdmin && !string.Equals(authenticatedTenantId, tenantId, StringComparison.OrdinalIgnoreCase)) { _logger.LogWarning("User {User} from tenant {AuthTenant} attempted to update configuration for tenant {TargetTenant}", userIdentifier, authenticatedTenantId, tenantId); @@ -86,9 +86,9 @@ namespace AutopilotMonitor.Functions.Functions.Config // Set the actual user identifier for audit logging config.UpdatedBy = userIdentifier; - // Protect GA-only fields from non-Galactic-Admin callers + // Protect GA-only fields from non-Global-Admin callers var existingConfig = await _configService.GetConfigurationAsync(tenantId); - if (!isGalacticAdmin) + if (!isGlobalAdmin) { if (config.AllowInsecureAgentRequests != existingConfig.AllowInsecureAgentRequests || config.BootstrapTokenEnabled != existingConfig.BootstrapTokenEnabled || diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Diagnostics/DiagnosticsDownloadFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Diagnostics/DiagnosticsDownloadFunction.cs index 19912212..3c436a5f 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Diagnostics/DiagnosticsDownloadFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Diagnostics/DiagnosticsDownloadFunction.cs @@ -16,16 +16,16 @@ namespace AutopilotMonitor.Functions.Functions.Diagnostics { private readonly ILogger _logger; private readonly TenantConfigurationService _configService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public DiagnosticsDownloadFunction( ILogger logger, TenantConfigurationService configService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _configService = configService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("DiagnosticsDownloadUrl")] @@ -52,8 +52,8 @@ namespace AutopilotMonitor.Functions.Functions.Diagnostics // Validate tenant access if (tenantId != userTenantId) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied." }); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Feedback/FeedbackFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Feedback/FeedbackFunction.cs index 6c90cbb5..10cb1a1e 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Feedback/FeedbackFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Feedback/FeedbackFunction.cs @@ -195,7 +195,7 @@ namespace AutopilotMonitor.Functions.Functions.Feedback } /// - /// Returns all feedback entries for the Galactic Admin dashboard. + /// Returns all feedback entries for the Global Admin dashboard. /// [Function("GetAllFeedback")] public async Task GetAll( diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Global/GlobalNotificationsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Global/GlobalNotificationsFunction.cs index a822b358..a8e12991 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Global/GlobalNotificationsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Global/GlobalNotificationsFunction.cs @@ -4,32 +4,32 @@ using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -namespace AutopilotMonitor.Functions.Functions.Galactic; +namespace AutopilotMonitor.Functions.Functions.Global; /// -/// API endpoints for managing persistent Galactic Admin notifications. -/// All endpoints require GalacticAdminOnly authorization (enforced by PolicyEnforcementMiddleware). +/// API endpoints for managing persistent Global Admin notifications. +/// All endpoints require GlobalAdminOnly authorization (enforced by PolicyEnforcementMiddleware). /// -public class GalacticNotificationsFunction +public class GlobalNotificationsFunction { - private readonly ILogger _logger; - private readonly GalacticNotificationService _notificationService; + private readonly ILogger _logger; + private readonly GlobalNotificationService _notificationService; - public GalacticNotificationsFunction( - ILogger logger, - GalacticNotificationService notificationService) + public GlobalNotificationsFunction( + ILogger logger, + GlobalNotificationService notificationService) { _logger = logger; _notificationService = notificationService; } /// - /// GET /api/galactic/notifications + /// GET /api/global/notifications /// Returns all active (non-dismissed) notifications, newest first. /// - [Function("GetGalacticNotifications")] + [Function("GetGlobalNotifications")] public async Task GetNotifications( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/notifications")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/notifications")] HttpRequestData req) { var notifications = await _notificationService.GetActiveNotificationsAsync(); @@ -39,12 +39,12 @@ public class GalacticNotificationsFunction } /// - /// POST /api/galactic/notifications/{notificationId}/dismiss + /// POST /api/global/notifications/{notificationId}/dismiss /// Dismisses a single notification. /// - [Function("DismissGalacticNotification")] + [Function("DismissGlobalNotification")] public async Task DismissNotification( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "galactic/notifications/{notificationId}/dismiss")] HttpRequestData req, + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "global/notifications/{notificationId}/dismiss")] HttpRequestData req, string notificationId) { var found = await _notificationService.DismissNotificationAsync(notificationId); @@ -62,12 +62,12 @@ public class GalacticNotificationsFunction } /// - /// POST /api/galactic/notifications/dismiss-all + /// POST /api/global/notifications/dismiss-all /// Dismisses all active notifications. /// - [Function("DismissAllGalacticNotifications")] + [Function("DismissAllGlobalNotifications")] public async Task DismissAll( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "galactic/notifications/dismiss-all")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "global/notifications/dismiss-all")] HttpRequestData req) { var dismissedCount = await _notificationService.DismissAllNotificationsAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs index 0c6d4eba..42dcd176 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs @@ -15,32 +15,32 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure; public class AuthFunction { private readonly ILogger _logger; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TenantConfigurationService _tenantConfigService; private readonly TenantAdminsService _tenantAdminsService; private readonly TableStorageService _storageService; private readonly PreviewWhitelistService _previewWhitelistService; private readonly TelegramNotificationService _telegramNotificationService; - private readonly GalacticNotificationService _galacticNotificationService; + private readonly GlobalNotificationService _globalNotificationService; public AuthFunction( ILogger logger, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TenantConfigurationService tenantConfigService, TenantAdminsService tenantAdminsService, TableStorageService storageService, PreviewWhitelistService previewWhitelistService, TelegramNotificationService telegramNotificationService, - GalacticNotificationService galacticNotificationService) + GlobalNotificationService globalNotificationService) { _logger = logger; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _tenantConfigService = tenantConfigService; _tenantAdminsService = tenantAdminsService; _storageService = storageService; _previewWhitelistService = previewWhitelistService; _telegramNotificationService = telegramNotificationService; - _galacticNotificationService = galacticNotificationService; + _globalNotificationService = globalNotificationService; } /// @@ -95,8 +95,8 @@ public class AuthFunction "Fire-and-forget Telegram notification failed for tenant {TenantId}", tenantId), TaskContinuationOptions.OnlyOnFaulted); - // Persistent in-app notification for Galactic Admins — best effort - _ = _galacticNotificationService.CreateNotificationAsync( + // Persistent in-app notification for Global Admins — best effort + _ = _globalNotificationService.CreateNotificationAsync( "preview_signup", "New Preview Signup", $"Tenant {tenantId} ({domain}), UPN: {upn}"); @@ -132,12 +132,12 @@ public class AuthFunction await _tenantConfigService.SaveConfigurationAsync(tenantConfig); } - // Check if user is galactic admin (must happen before preview gate) - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + // Check if user is global admin (must happen before preview gate) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); // Preview gate: only approved tenants get full portal access. - // Galactic Admins bypass the gate (they need access to manage the whitelist). - if (!isGalacticAdmin && !await _previewWhitelistService.IsApprovedAsync(tenantId)) + // Global Admins bypass the gate (they need access to manage the whitelist). + if (!isGlobalAdmin && !await _previewWhitelistService.IsApprovedAsync(tenantId)) { _logger.LogInformation("Tenant {TenantId} blocked by preview gate (user: {Upn})", tenantId, upn); @@ -181,7 +181,7 @@ public class AuthFunction upn, displayName, objectId, - isGalacticAdmin, + isGlobalAdmin, isTenantAdmin, role, canManageBootstrapTokens @@ -193,13 +193,13 @@ public class AuthFunction } /// - /// GET /api/auth/is-galactic-admin - /// Checks if the current user is a Galactic Admin + /// GET /api/auth/is-global-admin + /// Checks if the current user is a Global Admin /// - [Function("IsGalacticAdmin")] + [Function("IsGlobalAdmin")] [Authorize] - public async Task IsGalacticAdmin( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "auth/is-galactic-admin")] HttpRequestData req, + public async Task IsGlobalAdmin( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "auth/is-global-admin")] HttpRequestData req, FunctionContext context) { var principal = context.GetUser(); @@ -209,26 +209,26 @@ public class AuthFunction } var upn = principal.GetUserPrincipalName(); - var isAdmin = await _galacticAdminService.IsGalacticAdminAsync(upn); + var isAdmin = await _globalAdminService.IsGlobalAdminAsync(upn); var response = req.CreateResponse(HttpStatusCode.OK); - await response.WriteAsJsonAsync(new { isGalacticAdmin = isAdmin, upn }); + await response.WriteAsJsonAsync(new { isGlobalAdmin = isAdmin, upn }); return response; } /// - /// GET /api/auth/galactic-admins - /// Lists all Galactic Admins (only accessible by Galactic Admins) + /// GET /api/auth/global-admins + /// Lists all Global Admins (only accessible by Global Admins) /// - [Function("GetGalacticAdmins")] + [Function("GetGlobalAdmins")] [Authorize] - public async Task GetGalacticAdmins( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "auth/galactic-admins")] HttpRequestData req, + public async Task GetGlobalAdmins( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "auth/global-admins")] HttpRequestData req, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware - var admins = await _galacticAdminService.GetAllGalacticAdminsAsync(); + var admins = await _globalAdminService.GetAllGlobalAdminsAsync(); var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteAsJsonAsync(new { admins }); @@ -236,21 +236,21 @@ public class AuthFunction } /// - /// POST /api/auth/galactic-admins - /// Adds a new Galactic Admin (only accessible by existing Galactic Admins) + /// POST /api/auth/global-admins + /// Adds a new Global Admin (only accessible by existing Global Admins) /// - [Function("AddGalacticAdmin")] + [Function("AddGlobalAdmin")] [Authorize] - public async Task AddGalacticAdmin( - [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "auth/galactic-admins")] HttpRequestData req, + public async Task AddGlobalAdmin( + [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "auth/global-admins")] HttpRequestData req, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var principal = context.GetUser(); var currentUpn = principal?.GetUserPrincipalName(); // Parse request body - var body = await req.ReadFromJsonAsync(); + var body = await req.ReadFromJsonAsync(); if (body == null || string.IsNullOrWhiteSpace(body.Upn)) { var badRequestResponse = req.CreateResponse(HttpStatusCode.BadRequest); @@ -258,9 +258,9 @@ public class AuthFunction return badRequestResponse; } - var newAdmin = await _galacticAdminService.AddGalacticAdminAsync(body.Upn, currentUpn!); + var newAdmin = await _globalAdminService.AddGlobalAdminAsync(body.Upn, currentUpn!); - _logger.LogInformation($"Galactic Admin added: {body.Upn} by {currentUpn}"); + _logger.LogInformation($"Global Admin added: {body.Upn} by {currentUpn}"); var response = req.CreateResponse(HttpStatusCode.Created); await response.WriteAsJsonAsync(new { admin = newAdmin }); @@ -268,17 +268,17 @@ public class AuthFunction } /// - /// DELETE /api/auth/galactic-admins/{upn} - /// Removes a Galactic Admin (only accessible by existing Galactic Admins) + /// DELETE /api/auth/global-admins/{upn} + /// Removes a Global Admin (only accessible by existing Global Admins) /// - [Function("RemoveGalacticAdmin")] + [Function("RemoveGlobalAdmin")] [Authorize] - public async Task RemoveGalacticAdmin( - [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "auth/galactic-admins/{upn}")] HttpRequestData req, + public async Task RemoveGlobalAdmin( + [HttpTrigger(AuthorizationLevel.Anonymous, "delete", Route = "auth/global-admins/{upn}")] HttpRequestData req, string upn, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var principal = context.GetUser(); var currentUpn = principal?.GetUserPrincipalName(); @@ -286,16 +286,16 @@ public class AuthFunction if (upn.Equals(currentUpn, StringComparison.OrdinalIgnoreCase)) { var badRequestResponse = req.CreateResponse(HttpStatusCode.BadRequest); - await badRequestResponse.WriteAsJsonAsync(new { error = "You cannot remove yourself as a Galactic Admin" }); + await badRequestResponse.WriteAsJsonAsync(new { error = "You cannot remove yourself as a Global Admin" }); return badRequestResponse; } - await _galacticAdminService.RemoveGalacticAdminAsync(upn); + await _globalAdminService.RemoveGlobalAdminAsync(upn); - _logger.LogInformation($"Galactic Admin removed: {upn} by {currentUpn}"); + _logger.LogInformation($"Global Admin removed: {upn} by {currentUpn}"); var response = req.CreateResponse(HttpStatusCode.OK); - await response.WriteAsJsonAsync(new { message = "Galactic Admin removed successfully" }); + await response.WriteAsJsonAsync(new { message = "Global Admin removed successfully" }); return response; } @@ -317,7 +317,7 @@ public class AuthFunction } } -public class AddGalacticAdminRequest +public class AddGlobalAdminRequest { public string Upn { get; set; } = string.Empty; } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/HealthCheckFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/HealthCheckFunction.cs index 1723cfdd..8f393753 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/HealthCheckFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/HealthCheckFunction.cs @@ -79,7 +79,7 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure /// /// GET /api/health/detailed - /// Detailed health check with comprehensive system checks (Galactic Admin only) + /// Detailed health check with comprehensive system checks (Global Admin only) /// [Function("DetailedHealthCheck")] public async Task GetDetailedHealthCheck( @@ -88,7 +88,7 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure { _logger.LogInformation("Detailed health check requested"); - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware // Perform comprehensive health checks var healthCheckResult = await _healthCheckService.PerformAllChecksAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRAddToGroupFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRAddToGroupFunction.cs index f7e8bd04..0ab0a2e4 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRAddToGroupFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRAddToGroupFunction.cs @@ -12,14 +12,14 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure public class SignalRAddToGroupFunction { private readonly ILogger _logger; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public SignalRAddToGroupFunction( ILogger logger, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("AddToGroup")] @@ -54,21 +54,21 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure var userEmail = TenantHelper.GetUserIdentifier(req); // Validate tenant access - // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "galactic-admins" - // Users can only join groups for their own tenant (unless they are Galactic Admin) + // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "global-admins" + // Users can only join groups for their own tenant (unless they are Global Admin) - // Explicit validation for the galactic-admins group - if (request.GroupName == "galactic-admins") + // Explicit validation for the global-admins group + if (request.GroupName == "global-admins") { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userEmail); + if (!isGlobalAdmin) { - _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to join galactic-admins group without being a Galactic Admin"); + _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to join global-admins group without being a Global Admin"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Galactic Admins can join this group" }); + await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Global Admins can join this group" }); return new AddToGroupOutput { HttpResponse = forbiddenResponse }; } - _logger.LogInformation($"Galactic Admin {userEmail} joining galactic-admins group"); + _logger.LogInformation($"Global Admin {userEmail} joining global-admins group"); } else { @@ -84,10 +84,10 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure // Check if user is allowed to join this tenant's group if (requestedTenantId != userTenantId) { - // Check if user is Galactic Admin (they can join any tenant's group) - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); + // Check if user is Global Admin (they can join any tenant's group) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userEmail); - if (!isGalacticAdmin) + if (!isGlobalAdmin) { _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to join group for tenant {requestedTenantId}"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); @@ -96,7 +96,7 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure } else { - _logger.LogInformation($"Galactic Admin {userEmail} joining cross-tenant group: {request.GroupName}"); + _logger.LogInformation($"Global Admin {userEmail} joining cross-tenant group: {request.GroupName}"); } } } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRRemoveFromGroupFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRRemoveFromGroupFunction.cs index 77244fd3..4b261129 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRRemoveFromGroupFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/SignalRRemoveFromGroupFunction.cs @@ -12,14 +12,14 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure public class SignalRRemoveFromGroupFunction { private readonly ILogger _logger; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public SignalRRemoveFromGroupFunction( ILogger logger, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("RemoveFromGroup")] @@ -54,21 +54,21 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure var userEmail = TenantHelper.GetUserIdentifier(req); // Validate tenant access (same logic as AddToGroup) - // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "galactic-admins" - // Users can only leave groups for their own tenant (unless they are Galactic Admin) + // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "global-admins" + // Users can only leave groups for their own tenant (unless they are Global Admin) - // Explicit validation for the galactic-admins group - if (request.GroupName == "galactic-admins") + // Explicit validation for the global-admins group + if (request.GroupName == "global-admins") { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userEmail); + if (!isGlobalAdmin) { - _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to leave galactic-admins group without being a Galactic Admin"); + _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to leave global-admins group without being a Global Admin"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); - await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Galactic Admins can leave this group" }); + await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Global Admins can leave this group" }); return new RemoveFromGroupOutput { HttpResponse = forbiddenResponse }; } - _logger.LogInformation($"Galactic Admin {userEmail} leaving galactic-admins group"); + _logger.LogInformation($"Global Admin {userEmail} leaving global-admins group"); } else { @@ -84,10 +84,10 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure // Check if user is allowed to leave this tenant's group if (requestedTenantId != userTenantId) { - // Check if user is Galactic Admin (they can leave any tenant's group) - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); + // Check if user is Global Admin (they can leave any tenant's group) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userEmail); - if (!isGalacticAdmin) + if (!isGlobalAdmin) { _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to leave group for tenant {requestedTenantId}"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); @@ -96,7 +96,7 @@ namespace AutopilotMonitor.Functions.Functions.Infrastructure } else { - _logger.LogInformation($"Galactic Admin {userEmail} leaving cross-tenant group: {request.GroupName}"); + _logger.LogInformation($"Global Admin {userEmail} leaving cross-tenant group: {request.GroupName}"); } } } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalAppMetricsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalAppMetricsFunction.cs index 14e2708e..3b977a0c 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalAppMetricsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalAppMetricsFunction.cs @@ -7,29 +7,29 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { - public class GetGalacticAppMetricsFunction + public class GetGlobalAppMetricsFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TableStorageService _storageService; - public GetGalacticAppMetricsFunction( - ILogger logger, + public GetGlobalAppMetricsFunction( + ILogger logger, TableStorageService storageService) { _logger = logger; _storageService = storageService; } - [Function("GetGalacticAppMetrics")] + [Function("GetGlobalAppMetrics")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/metrics/app")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/metrics/app")] HttpRequestData req) { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"Fetching galactic app metrics (User: {userEmail})"); + _logger.LogInformation($"Fetching global app metrics (User: {userEmail})"); var query = System.Web.HttpUtility.ParseQueryString(req.Url.Query); var daysParam = query["days"]; @@ -94,7 +94,7 @@ namespace AutopilotMonitor.Functions.Functions.Metrics } catch (Exception ex) { - _logger.LogError(ex, "Error fetching galactic app metrics"); + _logger.LogError(ex, "Error fetching global app metrics"); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteAsJsonAsync(new { success = false, message = "Internal server error" }); return errorResponse; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicLocationSessionsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicLocationSessionsFunction.cs index 7304200e..18eee9da 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicLocationSessionsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicLocationSessionsFunction.cs @@ -7,26 +7,26 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { - public class GetGalacticGeographicLocationSessionsFunction + public class GetGlobalGeographicLocationSessionsFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TableStorageService _storageService; - public GetGalacticGeographicLocationSessionsFunction( - ILogger logger, + public GetGlobalGeographicLocationSessionsFunction( + ILogger logger, TableStorageService storageService) { _logger = logger; _storageService = storageService; } - [Function("GetGalacticGeographicLocationSessions")] + [Function("GetGlobalGeographicLocationSessions")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/metrics/geographic/sessions")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/metrics/geographic/sessions")] HttpRequestData req) { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); var query = System.Web.HttpUtility.ParseQueryString(req.Url.Query); @@ -45,7 +45,7 @@ namespace AutopilotMonitor.Functions.Functions.Metrics var groupBy = query["groupBy"] ?? "city"; - _logger.LogInformation("Fetching galactic sessions for location '{LocationKey}' ({Days}d, groupBy={GroupBy}) (User: {UserEmail})", + _logger.LogInformation("Fetching global sessions for location '{LocationKey}' ({Days}d, groupBy={GroupBy}) (User: {UserEmail})", locationKey, days, groupBy, userEmail); var cutoff = DateTime.UtcNow.AddDays(-days); @@ -59,7 +59,7 @@ namespace AutopilotMonitor.Functions.Functions.Metrics } catch (Exception ex) { - _logger.LogError(ex, "Error fetching galactic geographic location sessions"); + _logger.LogError(ex, "Error fetching global geographic location sessions"); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteAsJsonAsync(new { success = false, message = "Internal server error" }); return errorResponse; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicMetricsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicMetricsFunction.cs index a3eba177..2fb00b32 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicMetricsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalGeographicMetricsFunction.cs @@ -7,29 +7,29 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { - public class GetGalacticGeographicMetricsFunction + public class GetGlobalGeographicMetricsFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TableStorageService _storageService; - public GetGalacticGeographicMetricsFunction( - ILogger logger, + public GetGlobalGeographicMetricsFunction( + ILogger logger, TableStorageService storageService) { _logger = logger; _storageService = storageService; } - [Function("GetGalacticGeographicMetrics")] + [Function("GetGlobalGeographicMetrics")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/metrics/geographic")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/metrics/geographic")] HttpRequestData req) { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation("Fetching galactic geographic metrics (User: {UserEmail})", userEmail); + _logger.LogInformation("Fetching global geographic metrics (User: {UserEmail})", userEmail); var query = System.Web.HttpUtility.ParseQueryString(req.Url.Query); var daysParam = query["days"]; @@ -52,7 +52,7 @@ namespace AutopilotMonitor.Functions.Functions.Metrics } catch (Exception ex) { - _logger.LogError(ex, "Error fetching galactic geographic metrics"); + _logger.LogError(ex, "Error fetching global geographic metrics"); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteAsJsonAsync(new { success = false, message = "Internal server error" }); return errorResponse; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalPlatformMetricsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalPlatformMetricsFunction.cs index 81baa5c5..5582b4d5 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalPlatformMetricsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/GetGlobalPlatformMetricsFunction.cs @@ -7,31 +7,31 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { /// - /// Function for retrieving platform agent metrics (Galactic Admin only). + /// Function for retrieving platform agent metrics (Global Admin only). /// Returns per-session CPU, memory, network metrics with 5-minute backend cache. /// - public class GetGalacticPlatformMetricsFunction + public class GetGlobalPlatformMetricsFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly PlatformMetricsService _platformMetricsService; - public GetGalacticPlatformMetricsFunction( - ILogger logger, + public GetGlobalPlatformMetricsFunction( + ILogger logger, PlatformMetricsService platformMetricsService) { _logger = logger; _platformMetricsService = platformMetricsService; } - [Function("GetGalacticPlatformMetrics")] + [Function("GetGlobalPlatformMetrics")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/metrics/platform")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/metrics/platform")] HttpRequestData req) { _logger.LogInformation("Platform agent metrics requested"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var metrics = await _platformMetricsService.ComputePlatformMetricsAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/PlatformUsageMetricsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/PlatformUsageMetricsFunction.cs index dfca3ac6..74be7b97 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/PlatformUsageMetricsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Metrics/PlatformUsageMetricsFunction.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Metrics { /// - /// Function for retrieving platform usage metrics (Galactic Admin only) + /// Function for retrieving platform usage metrics (Global Admin only) /// public class PlatformUsageMetricsFunction { @@ -23,19 +23,19 @@ namespace AutopilotMonitor.Functions.Functions.Metrics } /// - /// GET /api/galactic/metrics/usage - Compute and return platform usage metrics - /// On-demand computation with 5-minute cache (Galactic Admin only) + /// GET /api/global/metrics/usage - Compute and return platform usage metrics + /// On-demand computation with 5-minute cache (Global Admin only) /// [Function("GetPlatformUsageMetrics")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/metrics/usage")] + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/metrics/usage")] HttpRequestData req) { _logger.LogInformation("Platform usage metrics requested"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware // Optional tenantId query parameter: when provided, return tenant-specific metrics var tenantId = req.Url.Query?.Contains("tenantId=") == true diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Progress/ProgressPortalFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Progress/ProgressPortalFunction.cs index c565dc05..39c53d7e 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Progress/ProgressPortalFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Progress/ProgressPortalFunction.cs @@ -17,16 +17,16 @@ public class ProgressPortalFunction { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public ProgressPortalFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } /// @@ -75,7 +75,7 @@ public class ProgressPortalFunction /// /// GET /api/progress/sessions/{sessionId}/events - /// Returns events for a specific session. Cross-tenant access only for Galactic Admins. + /// Returns events for a specific session. Cross-tenant access only for Global Admins. /// [Function("ProgressGetSessionEvents")] public async Task GetSessionEvents( @@ -115,11 +115,11 @@ public class ProgressPortalFunction return badRequest; } - // Cross-tenant access only for Galactic Admins + // Cross-tenant access only for Global Admins if (requestedTenantId != userTenantId) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); await forbiddenResponse.WriteAsJsonAsync(new @@ -133,7 +133,7 @@ public class ProgressPortalFunction return forbiddenResponse; } - _logger.LogInformation("{SessionPrefix} Galactic Admin {User} accessing cross-tenant progress events (tenant: {TenantId})", + _logger.LogInformation("{SessionPrefix} Global Admin {User} accessing cross-tenant progress events (tenant: {TenantId})", sessionPrefix, userIdentifier, requestedTenantId); } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportDownloadUrlFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportDownloadUrlFunction.cs index 769fa8b1..eac4ff55 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportDownloadUrlFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportDownloadUrlFunction.cs @@ -11,7 +11,7 @@ namespace AutopilotMonitor.Functions.Functions.Reports { /// /// Returns a short-lived SAS download URL for a session report blob stored in central blob storage. - /// Galactic Admin only. + /// Global Admin only. /// public class GetSessionReportDownloadUrlFunction { @@ -30,11 +30,11 @@ namespace AutopilotMonitor.Functions.Functions.Reports [Function("GetSessionReportDownloadUrl")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/session-reports/download-url")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/session-reports/download-url")] HttpRequestData req) { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var query = HttpUtility.ParseQueryString(req.Url.Query); var blobName = query["blobName"]; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportsFunction.cs index e100ab1a..651726ba 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/GetSessionReportsFunction.cs @@ -21,13 +21,13 @@ namespace AutopilotMonitor.Functions.Functions.Reports [Function("GetSessionReports")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/session-reports")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/session-reports")] HttpRequestData req) { _logger.LogInformation("GetSessionReports function processing request"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var reports = await _sessionReportService.GetAllReportsAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs index c0abd472..d5d984ed 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs @@ -13,24 +13,24 @@ namespace AutopilotMonitor.Functions.Functions.Reports private readonly ILogger _logger; private readonly SessionReportService _sessionReportService; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TelegramNotificationService _telegramNotificationService; - private readonly GalacticNotificationService _galacticNotificationService; + private readonly GlobalNotificationService _globalNotificationService; public SubmitSessionReportFunction( ILogger logger, SessionReportService sessionReportService, TableStorageService storageService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TelegramNotificationService telegramNotificationService, - GalacticNotificationService galacticNotificationService) + GlobalNotificationService globalNotificationService) { _logger = logger; _sessionReportService = sessionReportService; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _telegramNotificationService = telegramNotificationService; - _galacticNotificationService = galacticNotificationService; + _globalNotificationService = globalNotificationService; } [Function("SubmitSessionReport")] @@ -47,7 +47,7 @@ namespace AutopilotMonitor.Functions.Functions.Reports string userIdentifier = TenantHelper.GetUserIdentifier(req); // Still needed: GA check for audit log skip logic - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); // Parse request body var request = await req.ReadFromJsonAsync(); @@ -72,8 +72,8 @@ namespace AutopilotMonitor.Functions.Functions.Reports // Submit report var metadata = await _sessionReportService.SubmitReportAsync(request, userIdentifier); - // Log audit entry — skip for Galactic Admins - if (!isGalacticAdmin) + // Log audit entry — skip for Global Admins + if (!isGlobalAdmin) { await _storageService.LogAuditEntryAsync( request.TenantId, @@ -98,8 +98,8 @@ namespace AutopilotMonitor.Functions.Functions.Reports _ = _telegramNotificationService.SendSessionReportAsync( request.TenantId, userIdentifier, sessionId, metadata.ReportId, request.Comment ?? string.Empty); - // Persistent in-app notification for Galactic Admins — best effort - _ = _galacticNotificationService.CreateNotificationAsync( + // Persistent in-app notification for Global Admins — best effort + _ = _globalNotificationService.CreateNotificationAsync( "session_report", "New Session Report", $"{userIdentifier} — Session {sessionId} (Tenant: {request.TenantId})"); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/UpdateSessionReportNoteFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/UpdateSessionReportNoteFunction.cs index 62335c79..b6f44a5d 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/UpdateSessionReportNoteFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/UpdateSessionReportNoteFunction.cs @@ -10,7 +10,7 @@ using Newtonsoft.Json.Linq; namespace AutopilotMonitor.Functions.Functions.Reports { /// - /// Allows Galactic Admins to add or update an admin note on a submitted session report. + /// Allows Global Admins to add or update an admin note on a submitted session report. /// public class UpdateSessionReportNoteFunction { @@ -27,12 +27,12 @@ namespace AutopilotMonitor.Functions.Functions.Reports [Function("UpdateSessionReportNote")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "patch", Route = "galactic/session-reports/{reportId}/note")] HttpRequestData req, + [HttpTrigger(AuthorizationLevel.Anonymous, "patch", Route = "global/session-reports/{reportId}/note")] HttpRequestData req, string reportId) { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); if (string.IsNullOrEmpty(reportId)) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GetRuleResultsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GetRuleResultsFunction.cs index e254fa80..4d2ee230 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GetRuleResultsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GetRuleResultsFunction.cs @@ -11,25 +11,25 @@ namespace AutopilotMonitor.Functions.Functions.Rules /// /// Returns analysis results (rule evaluations) for a session. /// Supports on-demand re-analysis via ?reanalyze=true query parameter. - /// Galactic admins can request analysis for any tenant by passing ?tenantId=... + /// Global admins can request analysis for any tenant by passing ?tenantId=... /// public class GetRuleResultsFunction { private readonly ILogger _logger; private readonly TableStorageService _storageService; private readonly AnalyzeRuleService _analyzeRuleService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetRuleResultsFunction( ILogger logger, TableStorageService storageService, AnalyzeRuleService analyzeRuleService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; _analyzeRuleService = analyzeRuleService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetRuleResults")] @@ -46,18 +46,18 @@ namespace AutopilotMonitor.Functions.Functions.Rules var requestedTenantId = query["tenantId"]; var effectiveTenantId = string.IsNullOrEmpty(requestedTenantId) ? userTenantId : requestedTenantId; - // Cross-tenant access requires Galactic Admin + // Cross-tenant access requires Global Admin if (effectiveTenantId != userTenantId) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { success = false, message = "Access denied. You can only view analysis results for your own tenant." }); return forbidden; } - _logger.LogInformation($"Galactic Admin {userIdentifier} accessing cross-tenant analysis results (tenant: {effectiveTenantId})"); + _logger.LogInformation($"Global Admin {userIdentifier} accessing cross-tenant analysis results (tenant: {effectiveTenantId})"); } var reanalyze = string.Equals(query["reanalyze"], "true", StringComparison.OrdinalIgnoreCase); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GlobalRulesFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GlobalRulesFunction.cs index d851db11..cb85a2fb 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GlobalRulesFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/GlobalRulesFunction.cs @@ -7,17 +7,17 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Rules { /// - /// Galactic Admin endpoints for viewing rules across tenants. - /// Reads tenantId from query string (not JWT) so galactic admins can inspect any tenant. + /// Global Admin endpoints for viewing rules across tenants. + /// Reads tenantId from query string (not JWT) so global admins can inspect any tenant. /// - public class GalacticRulesFunction + public class GlobalRulesFunction { - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly GatherRuleService _gatherRuleService; private readonly AnalyzeRuleService _analyzeRuleService; - public GalacticRulesFunction( - ILogger logger, + public GlobalRulesFunction( + ILogger logger, GatherRuleService gatherRuleService, AnalyzeRuleService analyzeRuleService) { @@ -27,13 +27,13 @@ namespace AutopilotMonitor.Functions.Functions.Rules } /// - /// GET /api/galactic/rules/gather?tenantId=X - Get gather rules for any tenant (Galactic Admin only) + /// GET /api/global/rules/gather?tenantId=X - Get gather rules for any tenant (Global Admin only) /// - [Function("GetGalacticGatherRules")] + [Function("GetGlobalGatherRules")] public async Task GetGatherRules( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/rules/gather")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/rules/gather")] HttpRequestData req) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var tenantId = System.Web.HttpUtility.ParseQueryString(req.Url.Query ?? "").Get("tenantId"); if (string.IsNullOrEmpty(tenantId)) @@ -43,7 +43,7 @@ namespace AutopilotMonitor.Functions.Functions.Rules return badRequest; } - _logger.LogInformation("Galactic admin requesting gather rules for tenant {TenantId}", tenantId); + _logger.LogInformation("Global admin requesting gather rules for tenant {TenantId}", tenantId); var rules = await _gatherRuleService.GetAllRulesForTenantAsync(tenantId); @@ -53,13 +53,13 @@ namespace AutopilotMonitor.Functions.Functions.Rules } /// - /// GET /api/galactic/rules/analyze?tenantId=X - Get analyze rules for any tenant (Galactic Admin only) + /// GET /api/global/rules/analyze?tenantId=X - Get analyze rules for any tenant (Global Admin only) /// - [Function("GetGalacticAnalyzeRules")] + [Function("GetGlobalAnalyzeRules")] public async Task GetAnalyzeRules( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/rules/analyze")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/rules/analyze")] HttpRequestData req) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var tenantId = System.Web.HttpUtility.ParseQueryString(req.Url.Query ?? "").Get("tenantId"); if (string.IsNullOrEmpty(tenantId)) @@ -69,7 +69,7 @@ namespace AutopilotMonitor.Functions.Functions.Rules return badRequest; } - _logger.LogInformation("Galactic admin requesting analyze rules for tenant {TenantId}", tenantId); + _logger.LogInformation("Global admin requesting analyze rules for tenant {TenantId}", tenantId); var rules = await _analyzeRuleService.GetAllRulesForTenantAsync(tenantId); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/ImeLogPatternsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/ImeLogPatternsFunction.cs index f94ca251..9aeddd34 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/ImeLogPatternsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/ImeLogPatternsFunction.cs @@ -11,7 +11,7 @@ namespace AutopilotMonitor.Functions.Functions.Rules { /// /// API for managing IME log patterns (portal-facing, JWT auth). - /// Phase 1: Read-only for tenants, edit/reseed for Galactic Admins only. + /// Phase 1: Read-only for tenants, edit/reseed for Global Admins only. /// public class ImeLogPatternsFunction { @@ -43,7 +43,7 @@ namespace AutopilotMonitor.Functions.Functions.Rules [HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "rules/ime-log-patterns/{patternId}")] HttpRequestData req, string patternId) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware // Phase 1: Only global edits var globalEdit = req.Url.Query.Contains("global=true", StringComparison.OrdinalIgnoreCase); @@ -86,10 +86,10 @@ namespace AutopilotMonitor.Functions.Functions.Rules { try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var upn = TenantHelper.GetUserIdentifier(req); - _logger.LogInformation($"Reseed IME log patterns triggered by Galactic Admin {upn}"); + _logger.LogInformation($"Reseed IME log patterns triggered by Global Admin {upn}"); var (deleted, written) = await _patternService.ReseedBuiltInPatternsAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/PreviewWhitelistFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/PreviewWhitelistFunction.cs index e1cb4e18..a5007afc 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Rules/PreviewWhitelistFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Rules/PreviewWhitelistFunction.cs @@ -10,7 +10,7 @@ namespace AutopilotMonitor.Functions.Functions.Rules; /// /// CRUD endpoints for managing the Private Preview tenant whitelist. -/// All endpoints are Galactic Admin only (except notification-email which is AuthenticatedUser). +/// All endpoints are Global Admin only (except notification-email which is AuthenticatedUser). /// Temporary — remove after GA. /// public class PreviewWhitelistFunction @@ -45,7 +45,7 @@ public class PreviewWhitelistFunction [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "preview/whitelist")] HttpRequestData req, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var approved = await _previewWhitelistService.GetAllApprovedAsync(); @@ -65,7 +65,7 @@ public class PreviewWhitelistFunction string tenantId, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var principal = context.GetUser(); var upn = principal?.GetUserPrincipalName(); @@ -149,7 +149,7 @@ public class PreviewWhitelistFunction string tenantId, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var principal = context.GetUser(); var upn = principal?.GetUserPrincipalName(); @@ -164,7 +164,7 @@ public class PreviewWhitelistFunction /// /// GET /api/preview/notification-email/{tenantId} - /// Returns the notification email for a tenant. Galactic Admin only. + /// Returns the notification email for a tenant. Global Admin only. /// [Function("GetPreviewNotificationEmail")] [Authorize] @@ -224,7 +224,7 @@ public class PreviewWhitelistFunction /// /// POST /api/preview/send-welcome-email/{tenantId} - /// Sends (or resends) the Private Preview welcome email. Galactic Admin only. + /// Sends (or resends) the Private Preview welcome email. Global Admin only. /// Accepts optional { email } in body — if provided, saves it to PreviewWhitelist table before sending. /// [Function("SendPreviewWelcomeEmail")] @@ -234,7 +234,7 @@ public class PreviewWhitelistFunction string tenantId, FunctionContext context) { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware // If the caller provides an email in the body, save it first var body = await req.ReadFromJsonAsync(); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetAllSessionsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetAllSessionsFunction.cs index 67414608..22250af3 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetAllSessionsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetAllSessionsFunction.cs @@ -23,13 +23,13 @@ namespace AutopilotMonitor.Functions.Functions.Sessions [Function("GetAllSessions")] public async Task Run( - [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "galactic/sessions")] HttpRequestData req) + [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "global/sessions")] HttpRequestData req) { - _logger.LogInformation("GetAllSessions function processing request (Galactic Admin Mode)"); + _logger.LogInformation("GetAllSessions function processing request (Global Admin Mode)"); try { - // Authentication + GalacticAdminOnly authorization enforced by PolicyEnforcementMiddleware + // Authentication + GlobalAdminOnly authorization enforced by PolicyEnforcementMiddleware var userEmail = TenantHelper.GetUserIdentifier(req); var query = System.Web.HttpUtility.ParseQueryString(req.Url.Query); var cursor = query["cursor"]; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionEventsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionEventsFunction.cs index e4e01f5f..ea096211 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionEventsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionEventsFunction.cs @@ -12,16 +12,16 @@ namespace AutopilotMonitor.Functions.Functions.Sessions { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetSessionEventsFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetSessionEvents")] @@ -66,12 +66,12 @@ namespace AutopilotMonitor.Functions.Functions.Sessions return badRequest; } - // Validate tenant access: user must either own the tenant or be Galactic Admin + // Validate tenant access: user must either own the tenant or be Global Admin if (requestedTenantId != userTenantId) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); - if (!isGalacticAdmin) + if (!isGlobalAdmin) { _logger.LogWarning($"{sessionPrefix} User {userIdentifier} (tenant {userTenantId}) attempted to access session events for tenant {requestedTenantId}"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); @@ -87,7 +87,7 @@ namespace AutopilotMonitor.Functions.Functions.Sessions } else { - _logger.LogInformation($"{sessionPrefix} Galactic Admin {userIdentifier} accessing cross-tenant session events (tenant: {requestedTenantId})"); + _logger.LogInformation($"{sessionPrefix} Global Admin {userIdentifier} accessing cross-tenant session events (tenant: {requestedTenantId})"); } } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionFunction.cs index 2865d1ba..4464d0d3 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/GetSessionFunction.cs @@ -12,16 +12,16 @@ namespace AutopilotMonitor.Functions.Functions.Sessions { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetSessionFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetSession")] @@ -64,8 +64,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions if (!string.Equals(effectiveTenantId, userTenantId, StringComparison.OrdinalIgnoreCase)) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { _logger.LogWarning($"{sessionPrefix} User {userIdentifier} (tenant {userTenantId}) attempted to access session in tenant {effectiveTenantId}"); var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/MarkSessionFailedFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/MarkSessionFailedFunction.cs index fa40e680..c15ab824 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/MarkSessionFailedFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/MarkSessionFailedFunction.cs @@ -74,8 +74,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions }); // Send SignalR notification to update all clients in the tenant - // Only sent to tenant-specific group (not galactic-admins) to avoid flooding - // Galactic Admins can refresh or view session details to see status changes + // Only sent to tenant-specific group (not global-admins) to avoid flooding + // Global Admins can refresh or view session details to see status changes object? sessionDelta = updatedSession != null ? new { updatedSession.CurrentPhase, updatedSession.CurrentPhaseDetail, diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs index faa29981..8a5a87e2 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Sessions/RegisterSessionFunction.cs @@ -138,8 +138,8 @@ namespace AutopilotMonitor.Functions.Functions.Sessions await response.WriteAsJsonAsync(responseData); // Send SignalR notification for new session registration - // This is sent to BOTH tenant-specific group AND galactic-admins group - // so Galactic Admins can see new sessions from all tenants without being + // This is sent to BOTH tenant-specific group AND global-admins group + // so Global Admins can see new sessions from all tenants without being // flooded with every single event update var messagePayload = new { sessionId = registration.SessionId, @@ -154,17 +154,17 @@ namespace AutopilotMonitor.Functions.Functions.Sessions Arguments = new[] { messagePayload } }; - // 2. Galactic Admins notification (cross-tenant visibility) - var galacticAdminMessage = new SignalRMessageAction("newSession") + // 2. Global Admins notification (cross-tenant visibility) + var globalAdminMessage = new SignalRMessageAction("newSession") { - GroupName = "galactic-admins", + GroupName = "global-admins", Arguments = new[] { messagePayload } }; return new RegisterSessionOutput { HttpResponse = response, - SignalRMessages = new[] { tenantMessage, galacticAdminMessage } + SignalRMessages = new[] { tenantMessage, globalAdminMessage } }; } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetCpeMappingsFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetCpeMappingsFunction.cs index 5e994f9c..9fd54418 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetCpeMappingsFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetCpeMappingsFunction.cs @@ -36,7 +36,7 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { try { - // Galactic Admin only — enforced by PolicyEnforcementMiddleware + // Global Admin only — enforced by PolicyEnforcementMiddleware var tableClient = _storageService.GetTableClient(Constants.TableNames.VulnerabilityCache); // Same range query pattern used in VulnerabilityCorrelationService.EnsureMappingsLoadedAsync diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetSoftwareInventoryFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetSoftwareInventoryFunction.cs index 04e1214c..e28b9689 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetSoftwareInventoryFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetSoftwareInventoryFunction.cs @@ -13,22 +13,22 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { /// /// Returns the full software inventory for a tenant from the SoftwareInventory table. - /// Galactic Admin only. Query param: ?tenantId=... + /// Global Admin only. Query param: ?tenantId=... /// public class GetSoftwareInventoryFunction { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetSoftwareInventoryFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetSoftwareInventory")] @@ -37,7 +37,7 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { try { - // Galactic Admin only — enforced by PolicyEnforcementMiddleware + // Global Admin only — enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); var query = HttpUtility.ParseQueryString(req.Url.Query); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetUnmatchedSoftwareFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetUnmatchedSoftwareFunction.cs index 734c1d6b..a0527d01 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetUnmatchedSoftwareFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetUnmatchedSoftwareFunction.cs @@ -23,16 +23,16 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; public GetUnmatchedSoftwareFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService) + GlobalAdminService globalAdminService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; } [Function("GetUnmatchedSoftware")] @@ -41,7 +41,7 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { try { - // Galactic Admin only — enforced by PolicyEnforcementMiddleware + // Global Admin only — enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); // Query all SoftwareInventory entries across tenants and filter for unmatched (no CpeUri) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetVulnerabilityReportFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetVulnerabilityReportFunction.cs index 967358dd..1eb00c83 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetVulnerabilityReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/GetVulnerabilityReportFunction.cs @@ -16,24 +16,24 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability /// Returns the vulnerability correlation report for a session. /// Supports on-demand re-scan via ?rescan=true query parameter — re-runs the /// correlation against the stored inventory events with fresh CVE/KEV data. - /// Galactic admins can request reports for any tenant by passing ?tenantId=... + /// Global admins can request reports for any tenant by passing ?tenantId=... /// public class GetVulnerabilityReportFunction { private readonly ILogger _logger; private readonly TableStorageService _storageService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly VulnerabilityCorrelationService _correlationService; public GetVulnerabilityReportFunction( ILogger logger, TableStorageService storageService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, VulnerabilityCorrelationService correlationService) { _logger = logger; _storageService = storageService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _correlationService = correlationService; } @@ -51,18 +51,18 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability var requestedTenantId = query["tenantId"]; var effectiveTenantId = string.IsNullOrEmpty(requestedTenantId) ? userTenantId : requestedTenantId; - // Cross-tenant access requires Galactic Admin + // Cross-tenant access requires Global Admin if (effectiveTenantId != userTenantId) { - var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier); - if (!isGalacticAdmin) + var isGlobalAdmin = await _globalAdminService.IsGlobalAdminAsync(userIdentifier); + if (!isGlobalAdmin) { var forbidden = req.CreateResponse(HttpStatusCode.Forbidden); await forbidden.WriteAsJsonAsync(new { success = false, message = "Access denied. You can only view vulnerability reports for your own tenant." }); return forbidden; } - _logger.LogInformation("Galactic Admin {User} accessing cross-tenant vulnerability report (tenant: {TenantId})", + _logger.LogInformation("Global Admin {User} accessing cross-tenant vulnerability report (tenant: {TenantId})", userIdentifier, effectiveTenantId); } diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/SaveCustomCpeMappingFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/SaveCustomCpeMappingFunction.cs index dd16c6c7..250d8adb 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/SaveCustomCpeMappingFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/SaveCustomCpeMappingFunction.cs @@ -33,7 +33,7 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability { try { - // Galactic Admin only - require Authorization header + // Global Admin only - require Authorization header var authHeader = req.Headers.Contains("Authorization") ? req.Headers.GetValues("Authorization").FirstOrDefault() : null; diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/TriggerVulnerabilityDataSyncFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/TriggerVulnerabilityDataSyncFunction.cs index 4be3063b..a8e2db24 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/TriggerVulnerabilityDataSyncFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Vulnerability/TriggerVulnerabilityDataSyncFunction.cs @@ -13,13 +13,13 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability /// /// HTTP-triggered manual sync for vulnerability data (KEV catalog refresh). /// Supports ?reseed=true to force re-import of CPE mapping seed (GitHub first, embedded fallback). - /// Galactic Admin only. + /// Global Admin only. /// public class TriggerVulnerabilityDataSyncFunction { private readonly KevDataService _kevService; private readonly AdminConfigurationService _adminConfigService; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TableStorageService _storageService; private readonly GitHubRuleRepository _gitHubRepo; private readonly ILogger _logger; @@ -27,14 +27,14 @@ namespace AutopilotMonitor.Functions.Functions.Vulnerability public TriggerVulnerabilityDataSyncFunction( KevDataService kevService, AdminConfigurationService adminConfigService, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TableStorageService storageService, GitHubRuleRepository gitHubRepo, ILogger logger) { _kevService = kevService; _adminConfigService = adminConfigService; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _storageService = storageService; _gitHubRepo = gitHubRepo; _logger = logger; diff --git a/src/Backend/AutopilotMonitor.Functions/Helpers/SignalRGroupHelper.cs b/src/Backend/AutopilotMonitor.Functions/Helpers/SignalRGroupHelper.cs index 1504c6d9..5debed7d 100644 --- a/src/Backend/AutopilotMonitor.Functions/Helpers/SignalRGroupHelper.cs +++ b/src/Backend/AutopilotMonitor.Functions/Helpers/SignalRGroupHelper.cs @@ -2,7 +2,7 @@ namespace AutopilotMonitor.Functions.Helpers; /// /// Helper class for parsing SignalR group names. -/// Group formats: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "galactic-admins" +/// Group formats: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "global-admins" /// public static class SignalRGroupHelper { diff --git a/src/Backend/AutopilotMonitor.Functions/Middleware/PolicyEnforcementMiddleware.cs b/src/Backend/AutopilotMonitor.Functions/Middleware/PolicyEnforcementMiddleware.cs index ca212ecd..d7239d28 100644 --- a/src/Backend/AutopilotMonitor.Functions/Middleware/PolicyEnforcementMiddleware.cs +++ b/src/Backend/AutopilotMonitor.Functions/Middleware/PolicyEnforcementMiddleware.cs @@ -23,16 +23,16 @@ namespace AutopilotMonitor.Functions.Middleware; public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware { private readonly ILogger _logger; - private readonly GalacticAdminService _galacticAdminService; + private readonly GlobalAdminService _globalAdminService; private readonly TenantAdminsService _tenantAdminsService; public PolicyEnforcementMiddleware( ILogger logger, - GalacticAdminService galacticAdminService, + GlobalAdminService globalAdminService, TenantAdminsService tenantAdminsService) { _logger = logger; - _galacticAdminService = galacticAdminService; + _globalAdminService = globalAdminService; _tenantAdminsService = tenantAdminsService; } @@ -146,8 +146,8 @@ public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware case EndpointPolicy.BootstrapManagerOrGA: return await EvaluateBootstrapManagerOrGAAsync(tenantId, upn, userIdentifier); - case EndpointPolicy.GalacticAdminOnly: - return await EvaluateGalacticAdminOnlyAsync(upn, userIdentifier); + case EndpointPolicy.GlobalAdminOnly: + return await EvaluateGlobalAdminOnlyAsync(upn, userIdentifier); default: return CatalogDecisionResult.Deny(userIdentifier, "N/A", $"UnknownPolicy:{entry.Policy}"); @@ -160,8 +160,8 @@ public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(upn)) return CatalogDecisionResult.Deny(userIdentifier, "N/A", "MissingClaims"); - if (await _galacticAdminService.IsGalacticAdminAsync(upn)) - return CatalogDecisionResult.Allow(userIdentifier, "GalacticAdmin", "GABypass"); + if (await _globalAdminService.IsGlobalAdminAsync(upn)) + return CatalogDecisionResult.Allow(userIdentifier, "GlobalAdmin", "GABypass"); var role = await _tenantAdminsService.GetMemberRoleAsync(tenantId, upn); if (role == null) @@ -177,8 +177,8 @@ public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(upn)) return CatalogDecisionResult.Deny(userIdentifier, "N/A", "MissingClaims"); - if (await _galacticAdminService.IsGalacticAdminAsync(upn)) - return CatalogDecisionResult.Allow(userIdentifier, "GalacticAdmin", "GABypass"); + if (await _globalAdminService.IsGlobalAdminAsync(upn)) + return CatalogDecisionResult.Allow(userIdentifier, "GlobalAdmin", "GABypass"); if (await _tenantAdminsService.IsTenantAdminAsync(tenantId, upn)) return CatalogDecisionResult.Allow(userIdentifier, Constants.TenantRoles.Admin, "TenantAdmin"); @@ -194,8 +194,8 @@ public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(upn)) return CatalogDecisionResult.Deny(userIdentifier, "N/A", "MissingClaims"); - if (await _galacticAdminService.IsGalacticAdminAsync(upn)) - return CatalogDecisionResult.Allow(userIdentifier, "GalacticAdmin", "GABypass"); + if (await _globalAdminService.IsGlobalAdminAsync(upn)) + return CatalogDecisionResult.Allow(userIdentifier, "GlobalAdmin", "GABypass"); if (await _tenantAdminsService.CanManageBootstrapAsync(tenantId, upn)) return CatalogDecisionResult.Allow(userIdentifier, "BootstrapManager", "CanManageBootstrap"); @@ -205,16 +205,16 @@ public class PolicyEnforcementMiddleware : IFunctionsWorkerMiddleware return CatalogDecisionResult.Deny(userIdentifier, roleName, "NoBootstrapPermission"); } - private async Task EvaluateGalacticAdminOnlyAsync( + private async Task EvaluateGlobalAdminOnlyAsync( string? upn, string userIdentifier) { if (string.IsNullOrEmpty(upn)) return CatalogDecisionResult.Deny(userIdentifier, "N/A", "MissingClaims"); - if (await _galacticAdminService.IsGalacticAdminAsync(upn)) - return CatalogDecisionResult.Allow(userIdentifier, "GalacticAdmin", "IsGA"); + if (await _globalAdminService.IsGlobalAdminAsync(upn)) + return CatalogDecisionResult.Allow(userIdentifier, "GlobalAdmin", "IsGA"); - return CatalogDecisionResult.Deny(userIdentifier, "NonGA", "NotGalacticAdmin"); + return CatalogDecisionResult.Deny(userIdentifier, "NonGA", "NotGlobalAdmin"); } /// diff --git a/src/Backend/AutopilotMonitor.Functions/Program.cs b/src/Backend/AutopilotMonitor.Functions/Program.cs index 42028057..051f102e 100644 --- a/src/Backend/AutopilotMonitor.Functions/Program.cs +++ b/src/Backend/AutopilotMonitor.Functions/Program.cs @@ -104,7 +104,7 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -138,7 +138,7 @@ builder.Services.AddSingleton(); builder.Services.AddHttpClient(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); +builder.Services.AddSingleton(); var app = builder.Build(); diff --git a/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs b/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs index 2e8dcd57..2dc0fc7c 100644 --- a/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs +++ b/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs @@ -20,14 +20,14 @@ public enum EndpointPolicy /// Tenant member with Admin, Operator, or Viewer role. Tenant-scoped read access. MemberRead, - /// Tenant Admin or Galactic Admin. Tenant-scoped write access. + /// Tenant Admin or Global Admin. Tenant-scoped write access. TenantAdminOrGA, - /// Admin (always) or Operator with CanManageBootstrapTokens permission, or Galactic Admin. + /// Admin (always) or Operator with CanManageBootstrapTokens permission, or Global Admin. BootstrapManagerOrGA, - /// Galactic Admin only. Platform-wide access. - GalacticAdminOnly, + /// Global Admin only. Platform-wide access. + GlobalAdminOnly, } /// @@ -90,7 +90,7 @@ public static class EndpointAccessPolicyCatalog // ── AuthenticatedUser ─────────────────────────────────────────── new("GET", "auth/me", EndpointPolicy.AuthenticatedUser), - new("GET", "auth/is-galactic-admin", EndpointPolicy.AuthenticatedUser), + new("GET", "auth/is-global-admin", EndpointPolicy.AuthenticatedUser), new("POST", "realtime/negotiate", EndpointPolicy.AuthenticatedUser), new("POST", "realtime/groups/join", EndpointPolicy.AuthenticatedUser), new("POST", "realtime/groups/leave", EndpointPolicy.AuthenticatedUser), @@ -147,51 +147,51 @@ public static class EndpointAccessPolicyCatalog new("POST", "bootstrap/sessions", EndpointPolicy.BootstrapManagerOrGA), new("DELETE", "bootstrap/sessions/{code}", EndpointPolicy.BootstrapManagerOrGA), - // ── GalacticAdminOnly ─────────────────────────────────────────── - new("GET", "global/config", EndpointPolicy.GalacticAdminOnly), - new("PUT", "global/config", EndpointPolicy.GalacticAdminOnly), - new("POST", "global/config", EndpointPolicy.GalacticAdminOnly), - new("GET", "config/all", EndpointPolicy.GalacticAdminOnly), - new("GET", "auth/galactic-admins", EndpointPolicy.GalacticAdminOnly), - new("POST", "auth/galactic-admins", EndpointPolicy.GalacticAdminOnly), - new("DELETE", "auth/galactic-admins/{upn}", EndpointPolicy.GalacticAdminOnly), - new("GET", "preview/whitelist", EndpointPolicy.GalacticAdminOnly), - new("POST", "preview/whitelist/{tenantId}", EndpointPolicy.GalacticAdminOnly), - new("DELETE", "preview/whitelist/{tenantId}", EndpointPolicy.GalacticAdminOnly), - new("GET", "preview/notification-email/{tenantId}", EndpointPolicy.GalacticAdminOnly), - new("POST", "preview/send-welcome-email/{tenantId}", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/sessions", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/audit/logs", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/metrics/platform", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/metrics/app", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/metrics/geographic", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/metrics/geographic/sessions", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/metrics/usage", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/session-reports", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/session-reports/download-url", EndpointPolicy.GalacticAdminOnly), - new("PATCH", "galactic/session-reports/{reportId}/note", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/rules/gather", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/rules/analyze", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/devices/blocked", EndpointPolicy.GalacticAdminOnly), - new("GET", "devices/blocked", EndpointPolicy.GalacticAdminOnly), - new("POST", "devices/block", EndpointPolicy.GalacticAdminOnly), - new("DELETE", "devices/block/{encodedSerialNumber}", EndpointPolicy.GalacticAdminOnly), - new("GET", "versions/blocked", EndpointPolicy.GalacticAdminOnly), - new("POST", "versions/block", EndpointPolicy.GalacticAdminOnly), - new("DELETE", "versions/block/{encodedPattern}", EndpointPolicy.GalacticAdminOnly), - new("POST", "maintenance/trigger", EndpointPolicy.GalacticAdminOnly), + // ── GlobalAdminOnly ──────────────────────────────────────────── + new("GET", "global/config", EndpointPolicy.GlobalAdminOnly), + new("PUT", "global/config", EndpointPolicy.GlobalAdminOnly), + new("POST", "global/config", EndpointPolicy.GlobalAdminOnly), + new("GET", "config/all", EndpointPolicy.GlobalAdminOnly), + new("GET", "auth/global-admins", EndpointPolicy.GlobalAdminOnly), + new("POST", "auth/global-admins", EndpointPolicy.GlobalAdminOnly), + new("DELETE", "auth/global-admins/{upn}", EndpointPolicy.GlobalAdminOnly), + new("GET", "preview/whitelist", EndpointPolicy.GlobalAdminOnly), + new("POST", "preview/whitelist/{tenantId}", EndpointPolicy.GlobalAdminOnly), + new("DELETE", "preview/whitelist/{tenantId}", EndpointPolicy.GlobalAdminOnly), + new("GET", "preview/notification-email/{tenantId}", EndpointPolicy.GlobalAdminOnly), + new("POST", "preview/send-welcome-email/{tenantId}", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/sessions", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/audit/logs", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/metrics/platform", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/metrics/app", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/metrics/geographic", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/metrics/geographic/sessions", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/metrics/usage", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/session-reports", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/session-reports/download-url", EndpointPolicy.GlobalAdminOnly), + new("PATCH", "global/session-reports/{reportId}/note", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/rules/gather", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/rules/analyze", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/devices/blocked", EndpointPolicy.GlobalAdminOnly), + new("GET", "devices/blocked", EndpointPolicy.GlobalAdminOnly), + new("POST", "devices/block", EndpointPolicy.GlobalAdminOnly), + new("DELETE", "devices/block/{encodedSerialNumber}", EndpointPolicy.GlobalAdminOnly), + new("GET", "versions/blocked", EndpointPolicy.GlobalAdminOnly), + new("POST", "versions/block", EndpointPolicy.GlobalAdminOnly), + new("DELETE", "versions/block/{encodedPattern}", EndpointPolicy.GlobalAdminOnly), + new("POST", "maintenance/trigger", EndpointPolicy.GlobalAdminOnly), new("GET", "health/detailed", EndpointPolicy.AuthenticatedUser), - new("POST", "rules/reseed-from-github", EndpointPolicy.GalacticAdminOnly), - new("GET", "vulnerability/unmatched-software", EndpointPolicy.GalacticAdminOnly), - new("GET", "vulnerability/software-inventory", EndpointPolicy.GalacticAdminOnly), - new("POST", "vulnerability/sync", EndpointPolicy.GalacticAdminOnly), - new("POST", "vulnerability/cpe-mapping", EndpointPolicy.GalacticAdminOnly), - new("GET", "vulnerability/cpe-mappings", EndpointPolicy.GalacticAdminOnly), - new("POST", "rules/ime-log-patterns/reseed", EndpointPolicy.GalacticAdminOnly), - new("GET", "feedback/all", EndpointPolicy.GalacticAdminOnly), - new("GET", "galactic/notifications", EndpointPolicy.GalacticAdminOnly), - new("POST", "galactic/notifications/dismiss-all", EndpointPolicy.GalacticAdminOnly), - new("POST", "galactic/notifications/{notificationId}/dismiss", EndpointPolicy.GalacticAdminOnly), + new("POST", "rules/reseed-from-github", EndpointPolicy.GlobalAdminOnly), + new("GET", "vulnerability/unmatched-software", EndpointPolicy.GlobalAdminOnly), + new("GET", "vulnerability/software-inventory", EndpointPolicy.GlobalAdminOnly), + new("POST", "vulnerability/sync", EndpointPolicy.GlobalAdminOnly), + new("POST", "vulnerability/cpe-mapping", EndpointPolicy.GlobalAdminOnly), + new("GET", "vulnerability/cpe-mappings", EndpointPolicy.GlobalAdminOnly), + new("POST", "rules/ime-log-patterns/reseed", EndpointPolicy.GlobalAdminOnly), + new("GET", "feedback/all", EndpointPolicy.GlobalAdminOnly), + new("GET", "global/notifications", EndpointPolicy.GlobalAdminOnly), + new("POST", "global/notifications/dismiss-all", EndpointPolicy.GlobalAdminOnly), + new("POST", "global/notifications/{notificationId}/dismiss", EndpointPolicy.GlobalAdminOnly), }; /// diff --git a/src/Backend/AutopilotMonitor.Functions/Security/SecurityValidator.cs b/src/Backend/AutopilotMonitor.Functions/Security/SecurityValidator.cs index 7b048a1f..7a7403ff 100644 --- a/src/Backend/AutopilotMonitor.Functions/Security/SecurityValidator.cs +++ b/src/Backend/AutopilotMonitor.Functions/Security/SecurityValidator.cs @@ -172,7 +172,7 @@ namespace AutopilotMonitor.Functions.Security // Security validation is always enforced (no longer configurable per tenant) // Hard gate: tenant must enable at least one device validation method before agent traffic is accepted. - // Galactic Admins can set AllowInsecureAgentRequests=true in the config row for test tenants. + // Global Admins can set AllowInsecureAgentRequests=true in the config row for test tenants. if (!config.ValidateAutopilotDevice && !config.ValidateCorporateIdentifier && !config.AllowInsecureAgentRequests) { return new SecurityValidationResult diff --git a/src/Backend/AutopilotMonitor.Functions/Services/GalacticAdminService.cs b/src/Backend/AutopilotMonitor.Functions/Services/GlobalAdminService.cs similarity index 60% rename from src/Backend/AutopilotMonitor.Functions/Services/GalacticAdminService.cs rename to src/Backend/AutopilotMonitor.Functions/Services/GlobalAdminService.cs index 803cf692..034057d3 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/GalacticAdminService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/GlobalAdminService.cs @@ -7,20 +7,20 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services; /// -/// Service for managing Galactic Admin permissions -/// Galactic Admins can access cross-tenant data and perform platform-wide operations +/// Service for managing Global Admin permissions +/// Global Admins can access cross-tenant data and perform platform-wide operations /// -public class GalacticAdminService +public class GlobalAdminService { private readonly TableServiceClient _tableServiceClient; private readonly IMemoryCache _cache; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(5); - public GalacticAdminService( + public GlobalAdminService( IConfiguration configuration, IMemoryCache cache, - ILogger logger) + ILogger logger) { _cache = cache; _logger = logger; @@ -30,37 +30,37 @@ public class GalacticAdminService } /// - /// Checks if a UPN is a Galactic Admin + /// Checks if a UPN is a Global Admin /// Uses caching for performance /// /// User Principal Name (e.g., oliver@contoso.com) - /// True if the user is a Galactic Admin - public async Task IsGalacticAdminAsync(string? upn) + /// True if the user is a Global Admin + public async Task IsGlobalAdminAsync(string? upn) { if (string.IsNullOrWhiteSpace(upn)) { - _logger.LogDebug("IsGalacticAdminAsync: UPN is null or empty"); + _logger.LogDebug("IsGlobalAdminAsync: UPN is null or empty"); return false; } // Normalize UPN to lowercase for case-insensitive comparison upn = upn.ToLowerInvariant(); - _logger.LogInformation($"Checking if user is Galactic Admin: {upn}"); + _logger.LogInformation($"Checking if user is Global Admin: {upn}"); // Check cache first - var cacheKey = $"galactic-admin:{upn}"; + var cacheKey = $"global-admin:{upn}"; if (_cache.TryGetValue(cacheKey, out var isAdmin)) { - _logger.LogInformation($"Galactic Admin check (from cache): {upn} -> {isAdmin}"); + _logger.LogInformation($"Global Admin check (from cache): {upn} -> {isAdmin}"); return isAdmin; } // Query Table Storage - _logger.LogInformation($"Querying Table Storage for Galactic Admin: {upn}"); - var admin = await GetGalacticAdminAsync(upn); + _logger.LogInformation($"Querying Table Storage for Global Admin: {upn}"); + var admin = await GetGlobalAdminAsync(upn); var result = admin != null && admin.IsEnabled; - _logger.LogInformation($"Galactic Admin check result: {upn} -> {result} (Entity found: {admin != null}, IsEnabled: {admin?.IsEnabled})"); + _logger.LogInformation($"Global Admin check result: {upn} -> {result} (Entity found: {admin != null}, IsEnabled: {admin?.IsEnabled})"); // Cache the result _cache.Set(cacheKey, result, _cacheDuration); @@ -69,52 +69,52 @@ public class GalacticAdminService } /// - /// Gets a Galactic Admin entity by UPN + /// Gets a Global Admin entity by UPN /// - private async Task GetGalacticAdminAsync(string upn) + private async Task GetGlobalAdminAsync(string upn) { try { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticAdmins); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalAdmins); var normalizedUpn = upn.ToLowerInvariant(); - _logger.LogDebug($"Querying Table Storage - PartitionKey: 'GalacticAdmins', RowKey: '{normalizedUpn}'"); + _logger.LogDebug($"Querying Table Storage - PartitionKey: 'GlobalAdmins', RowKey: '{normalizedUpn}'"); - // PartitionKey = "GalacticAdmins", RowKey = UPN - var entity = await tableClient.GetEntityAsync( - "GalacticAdmins", + // PartitionKey = "GlobalAdmins", RowKey = UPN + var entity = await tableClient.GetEntityAsync( + "GlobalAdmins", normalizedUpn ); - _logger.LogDebug($"Galactic Admin entity found for {normalizedUpn}"); + _logger.LogDebug($"Global Admin entity found for {normalizedUpn}"); return entity?.Value; } catch (Azure.RequestFailedException ex) when (ex.Status == 404) { // Entity not found - _logger.LogDebug($"Galactic Admin entity NOT found for {upn} (404)"); + _logger.LogDebug($"Global Admin entity NOT found for {upn} (404)"); return null; } catch (Exception ex) { - _logger.LogError(ex, $"Error querying Galactic Admin for {upn}"); + _logger.LogError(ex, $"Error querying Global Admin for {upn}"); return null; } } /// - /// Adds a user as a Galactic Admin + /// Adds a user as a Global Admin /// /// User Principal Name /// UPN of the admin who is adding this user - public async Task AddGalacticAdminAsync(string upn, string addedBy) + public async Task AddGlobalAdminAsync(string upn, string addedBy) { upn = upn.ToLowerInvariant(); addedBy = addedBy.ToLowerInvariant(); - var entity = new GalacticAdminEntity + var entity = new GlobalAdminEntity { - PartitionKey = "GalacticAdmins", + PartitionKey = "GlobalAdmins", RowKey = upn, Upn = upn, IsEnabled = true, @@ -122,59 +122,59 @@ public class GalacticAdminService AddedBy = addedBy }; - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticAdmins); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalAdmins); await tableClient.UpsertEntityAsync(entity); // Invalidate cache - _cache.Remove($"galactic-admin:{upn}"); + _cache.Remove($"global-admin:{upn}"); return entity; } /// - /// Removes a user from Galactic Admins + /// Removes a user from Global Admins /// - public async Task RemoveGalacticAdminAsync(string upn) + public async Task RemoveGlobalAdminAsync(string upn) { upn = upn.ToLowerInvariant(); - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticAdmins); - await tableClient.DeleteEntityAsync("GalacticAdmins", upn); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalAdmins); + await tableClient.DeleteEntityAsync("GlobalAdmins", upn); // Invalidate cache - _cache.Remove($"galactic-admin:{upn}"); + _cache.Remove($"global-admin:{upn}"); } /// - /// Disables (but does not delete) a Galactic Admin + /// Disables (but does not delete) a Global Admin /// - public async Task DisableGalacticAdminAsync(string upn) + public async Task DisableGlobalAdminAsync(string upn) { upn = upn.ToLowerInvariant(); - var admin = await GetGalacticAdminAsync(upn); + var admin = await GetGlobalAdminAsync(upn); if (admin != null) { admin.IsEnabled = false; - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticAdmins); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalAdmins); await tableClient.UpdateEntityAsync(admin, Azure.ETag.All); // Invalidate cache - _cache.Remove($"galactic-admin:{upn}"); + _cache.Remove($"global-admin:{upn}"); } } /// - /// Gets all Galactic Admins + /// Gets all Global Admins /// - public async Task> GetAllGalacticAdminsAsync() + public async Task> GetAllGlobalAdminsAsync() { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticAdmins); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalAdmins); - var admins = new List(); - await foreach (var entity in tableClient.QueryAsync( - filter: $"PartitionKey eq 'GalacticAdmins'")) + var admins = new List(); + await foreach (var entity in tableClient.QueryAsync( + filter: $"PartitionKey eq 'GlobalAdmins'")) { admins.Add(entity); } @@ -183,7 +183,7 @@ public class GalacticAdminService } /// - /// Clears the cache for all Galactic Admins + /// Clears the cache for all Global Admins /// Useful after bulk updates /// public void ClearCache() @@ -195,11 +195,11 @@ public class GalacticAdminService } /// -/// Entity representing a Galactic Admin in Table Storage +/// Entity representing a Global Admin in Table Storage /// -public class GalacticAdminEntity : ITableEntity +public class GlobalAdminEntity : ITableEntity { - public string PartitionKey { get; set; } = "GalacticAdmins"; + public string PartitionKey { get; set; } = "GlobalAdmins"; public string RowKey { get; set; } = string.Empty; // UPN in lowercase public DateTimeOffset? Timestamp { get; set; } public Azure.ETag ETag { get; set; } diff --git a/src/Backend/AutopilotMonitor.Functions/Services/GalacticNotificationService.cs b/src/Backend/AutopilotMonitor.Functions/Services/GlobalNotificationService.cs similarity index 72% rename from src/Backend/AutopilotMonitor.Functions/Services/GalacticNotificationService.cs rename to src/Backend/AutopilotMonitor.Functions/Services/GlobalNotificationService.cs index bc121f3b..ab10e6de 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/GalacticNotificationService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/GlobalNotificationService.cs @@ -7,10 +7,10 @@ using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Services; /// -/// Entity for persistent Galactic Admin notifications stored in Table Storage. +/// Entity for persistent Global Admin notifications stored in Table Storage. /// All GAs share the same notification pool; dismiss is global. /// -public class GalacticNotificationEntity : ITableEntity +public class GlobalNotificationEntity : ITableEntity { public string PartitionKey { get; set; } = "notifications"; public string RowKey { get; set; } = string.Empty; // invertedTicks_notificationId (newest-first) @@ -27,9 +27,9 @@ public class GalacticNotificationEntity : ITableEntity } /// -/// DTO returned by the API for galactic notifications. +/// DTO returned by the API for global notifications. /// -public class GalacticNotificationDto +public class GlobalNotificationDto { public string Id { get; set; } = string.Empty; public string Type { get; set; } = "info"; @@ -40,17 +40,17 @@ public class GalacticNotificationDto } /// -/// Service for managing persistent Galactic Admin in-app notifications. +/// Service for managing persistent Global Admin in-app notifications. /// Notifications survive page reloads and persist until actively dismissed. /// -public class GalacticNotificationService +public class GlobalNotificationService { private readonly TableServiceClient _tableServiceClient; - private readonly ILogger _logger; + private readonly ILogger _logger; - public GalacticNotificationService( + public GlobalNotificationService( IConfiguration configuration, - ILogger logger) + ILogger logger) { _logger = logger; var connectionString = configuration["AzureTableStorageConnectionString"]; @@ -65,11 +65,11 @@ public class GalacticNotificationService { try { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticNotifications); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalNotifications); var notificationId = Guid.NewGuid().ToString("N")[..12]; var invertedTicks = (DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks).ToString("D19"); - var entity = new GalacticNotificationEntity + var entity = new GlobalNotificationEntity { PartitionKey = "notifications", RowKey = $"{invertedTicks}_{notificationId}", @@ -83,28 +83,28 @@ public class GalacticNotificationService }; await tableClient.UpsertEntityAsync(entity); - _logger.LogInformation("Galactic notification created: {NotificationId} ({Type})", notificationId, type); + _logger.LogInformation("Global notification created: {NotificationId} ({Type})", notificationId, type); } catch (Exception ex) { - _logger.LogWarning(ex, "Failed to create galactic notification ({Type}: {Title})", type, title); + _logger.LogWarning(ex, "Failed to create global notification ({Type}: {Title})", type, title); } } /// /// Returns all active (non-dismissed) notifications, newest first. /// - public async Task> GetActiveNotificationsAsync() + public async Task> GetActiveNotificationsAsync() { try { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticNotifications); - var notifications = new List(); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalNotifications); + var notifications = new List(); - await foreach (var entity in tableClient.QueryAsync( + await foreach (var entity in tableClient.QueryAsync( e => e.PartitionKey == "notifications" && !e.Dismissed)) { - notifications.Add(new GalacticNotificationDto + notifications.Add(new GlobalNotificationDto { Id = entity.NotificationId, Type = entity.Type, @@ -119,13 +119,13 @@ public class GalacticNotificationService } catch (RequestFailedException ex) when (ex.Status == 404) { - _logger.LogWarning("GalacticNotifications table not found — returning empty list"); - return new List(); + _logger.LogWarning("GlobalNotifications table not found — returning empty list"); + return new List(); } catch (Exception ex) { - _logger.LogError(ex, "Failed to retrieve galactic notifications"); - return new List(); + _logger.LogError(ex, "Failed to retrieve global notifications"); + return new List(); } } @@ -137,14 +137,14 @@ public class GalacticNotificationService { try { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticNotifications); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalNotifications); - await foreach (var entity in tableClient.QueryAsync( + await foreach (var entity in tableClient.QueryAsync( e => e.PartitionKey == "notifications" && e.NotificationId == notificationId)) { entity.Dismissed = true; await tableClient.UpdateEntityAsync(entity, entity.ETag, TableUpdateMode.Replace); - _logger.LogInformation("Galactic notification dismissed: {NotificationId}", notificationId); + _logger.LogInformation("Global notification dismissed: {NotificationId}", notificationId); return true; } @@ -152,7 +152,7 @@ public class GalacticNotificationService } catch (Exception ex) { - _logger.LogError(ex, "Failed to dismiss galactic notification {NotificationId}", notificationId); + _logger.LogError(ex, "Failed to dismiss global notification {NotificationId}", notificationId); return false; } } @@ -164,10 +164,10 @@ public class GalacticNotificationService { try { - var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GalacticNotifications); + var tableClient = _tableServiceClient.GetTableClient(Constants.TableNames.GlobalNotifications); var count = 0; - await foreach (var entity in tableClient.QueryAsync( + await foreach (var entity in tableClient.QueryAsync( e => e.PartitionKey == "notifications" && !e.Dismissed)) { entity.Dismissed = true; @@ -175,12 +175,12 @@ public class GalacticNotificationService count++; } - _logger.LogInformation("Dismissed {Count} galactic notifications", count); + _logger.LogInformation("Dismissed {Count} global notifications", count); return count; } catch (Exception ex) { - _logger.LogError(ex, "Failed to dismiss all galactic notifications"); + _logger.LogError(ex, "Failed to dismiss all global notifications"); return 0; } } diff --git a/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs b/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs index 98718828..ae741ec5 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/ImeLogPatternService.cs @@ -109,7 +109,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Updates a built-in IME log pattern globally (Galactic Admin only). + /// Updates a built-in IME log pattern globally (Global Admin only). /// Modifies the global definition that all tenants inherit. /// public async Task UpdateGlobalPatternAsync(ImeLogPattern pattern) @@ -127,7 +127,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Deletes a built-in IME log pattern from the global partition (Galactic Admin only). + /// Deletes a built-in IME log pattern from the global partition (Global Admin only). /// public async Task DeleteGlobalPatternAsync(string patternId) { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/PreviewWhitelistService.cs b/src/Backend/AutopilotMonitor.Functions/Services/PreviewWhitelistService.cs index 1a291f5c..3f3c35ad 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/PreviewWhitelistService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/PreviewWhitelistService.cs @@ -98,7 +98,7 @@ public class PreviewWhitelistService } /// - /// Returns all approved tenants (for Galactic Admin overview). + /// Returns all approved tenants (for Global Admin overview). /// public async Task> GetAllApprovedAsync() { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Maintenance.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Maintenance.cs index 29dbdbf1..2b53c31c 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Maintenance.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Maintenance.cs @@ -83,7 +83,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Gets audit log entries across all tenants (Galactic Admin Mode) + /// Gets audit log entries across all tenants (Global Admin Mode) /// public async Task> GetAllAuditLogsAsync(int maxResults = 100) { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Metrics.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Metrics.cs index e52dfa5b..a13da8e8 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Metrics.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Metrics.cs @@ -239,7 +239,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Gets all app install summaries across all tenants (for galactic admin mode) + /// Gets all app install summaries across all tenants (for global admin mode) /// public async Task> GetAllAppInstallSummariesAsync() { @@ -488,7 +488,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Gets user activity metrics across all tenants (for galactic admin) + /// Gets user activity metrics across all tenants (for global admin) /// public async Task GetAllUserActivityMetricsAsync() { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs index d64df73c..1cc419c3 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TableStorageService.Sessions.cs @@ -661,7 +661,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Gets all sessions across all tenants (galactic admin mode), ordered newest-first, + /// Gets all sessions across all tenants (global admin mode), ordered newest-first, /// with cursor-based pagination. Queries SessionsIndex cross-partition. /// Cross-partition queries require in-memory sort since Azure Table Storage only /// guarantees RowKey order within a single partition. @@ -672,7 +672,7 @@ namespace AutopilotMonitor.Functions.Services { var indexTableClient = _tableServiceClient.GetTableClient(Constants.TableNames.SessionsIndex); - // For galactic queries, use StartedAt filter derived from cursor for efficiency + // For global queries, use StartedAt filter derived from cursor for efficiency string? filter = null; if (!string.IsNullOrEmpty(cursor)) { @@ -745,7 +745,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Fallback: queries the Sessions table directly for galactic admin (pre-migration). + /// Fallback: queries the Sessions table directly for global admin (pre-migration). /// private async Task GetAllSessionsFromPrimaryTableAsync(int maxResults) { diff --git a/src/Backend/AutopilotMonitor.Functions/Services/TenantConfigurationService.cs b/src/Backend/AutopilotMonitor.Functions/Services/TenantConfigurationService.cs index 923cb6d8..2657c850 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/TenantConfigurationService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/TenantConfigurationService.cs @@ -165,7 +165,7 @@ namespace AutopilotMonitor.Functions.Services } /// - /// Gets all tenant configurations (for Galactic Admin use) + /// Gets all tenant configurations (for Global Admin use) /// public async Task> GetAllConfigurationsAsync() { diff --git a/src/Shared/AutopilotMonitor.Shared/Constants.cs b/src/Shared/AutopilotMonitor.Shared/Constants.cs index ed841bb2..131a1b1f 100644 --- a/src/Shared/AutopilotMonitor.Shared/Constants.cs +++ b/src/Shared/AutopilotMonitor.Shared/Constants.cs @@ -231,7 +231,7 @@ namespace AutopilotMonitor.Shared public const string AdminConfiguration = "AdminConfiguration"; // Admin tables - public const string GalacticAdmins = "GalacticAdmins"; + public const string GlobalAdmins = "GlobalAdmins"; public const string TenantAdmins = "TenantAdmins"; // Preview gating (temporary — remove after GA) @@ -250,8 +250,8 @@ namespace AutopilotMonitor.Shared // Bootstrap sessions (OOBE pre-enrollment agent deployment) public const string BootstrapSessions = "BootstrapSessions"; - // Galactic Admin in-app notifications (persistent until dismissed) - public const string GalacticNotifications = "GalacticNotifications"; + // Global Admin in-app notifications (persistent until dismissed) + public const string GlobalNotifications = "GlobalNotifications"; // Vulnerability data cache (CPE mappings, CVE data) public const string VulnerabilityCache = "VulnerabilityCache"; @@ -282,7 +282,7 @@ namespace AutopilotMonitor.Shared PlatformStats, TenantConfiguration, AdminConfiguration, - GalacticAdmins, + GlobalAdmins, TenantAdmins, PreviewWhitelist, PreviewConfig, @@ -290,7 +290,7 @@ namespace AutopilotMonitor.Shared BlockedVersions, SessionReports, BootstrapSessions, - GalacticNotifications, + GlobalNotifications, VulnerabilityCache, VulnerabilityReports, SoftwareInventory diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Config/AdminConfiguration.cs b/src/Shared/AutopilotMonitor.Shared/Models/Config/AdminConfiguration.cs index ee45bd81..8df4e7cb 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Config/AdminConfiguration.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Config/AdminConfiguration.cs @@ -5,7 +5,7 @@ using System.Text.Json; namespace AutopilotMonitor.Shared.Models { /// - /// Global platform configuration managed by Galactic Admins + /// Global platform configuration managed by Global Admins /// Stored in Azure Table Storage with single instance /// PartitionKey = "GlobalConfig" /// RowKey = "config" @@ -28,7 +28,7 @@ namespace AutopilotMonitor.Shared.Models public DateTime LastUpdated { get; set; } /// - /// Updated by (Galactic Admin user email) + /// Updated by (Global Admin user email) /// public string UpdatedBy { get; set; } diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Config/TenantConfiguration.cs b/src/Shared/AutopilotMonitor.Shared/Models/Config/TenantConfiguration.cs index 1bd751f4..4358a758 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Config/TenantConfiguration.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Config/TenantConfiguration.cs @@ -74,7 +74,7 @@ namespace AutopilotMonitor.Shared.Models /// /// Optional custom rate limit for this tenant (overrides RateLimitRequestsPerMinute) /// If set (not null), this custom value takes precedence over the global default - /// Note: This is only configurable by Galactic Admins directly in the database + /// Note: This is only configurable by Global Admins directly in the database /// public int? CustomRateLimitRequestsPerMinute { get; set; } = null; @@ -105,7 +105,7 @@ namespace AutopilotMonitor.Shared.Models public bool ValidateCorporateIdentifier { get; set; } = false; /// - /// Emergency bypass for agent security gate (Galactic Admin use only). + /// Emergency bypass for agent security gate (Global Admin use only). /// If true, agent requests are accepted even when ValidateAutopilotDevice is false. /// Default: false /// @@ -310,7 +310,7 @@ namespace AutopilotMonitor.Shared.Models /// Whether OOBE Bootstrap Sessions are enabled for this tenant. /// When false (default), the Bootstrap Sessions feature is hidden in the UI /// and all bootstrap API endpoints reject requests for this tenant. - /// Only configurable by Galactic Admins. + /// Only configurable by Global Admins. /// public bool BootstrapTokenEnabled { get; set; } = false; @@ -320,7 +320,7 @@ namespace AutopilotMonitor.Shared.Models /// Whether the Unrestricted Mode feature is available for this tenant. /// When false (default), the Unrestricted Mode section is hidden in the tenant settings UI /// and UnrestrictedMode cannot be activated by tenant admins. - /// Only configurable by Galactic Admins. + /// Only configurable by Global Admins. /// public bool UnrestrictedModeEnabled { get; set; } = false; diff --git a/src/Shared/AutopilotMonitor.Shared/Models/Diagnostics/DiagnosticsLogPath.cs b/src/Shared/AutopilotMonitor.Shared/Models/Diagnostics/DiagnosticsLogPath.cs index 64a659db..b3808b72 100644 --- a/src/Shared/AutopilotMonitor.Shared/Models/Diagnostics/DiagnosticsLogPath.cs +++ b/src/Shared/AutopilotMonitor.Shared/Models/Diagnostics/DiagnosticsLogPath.cs @@ -2,7 +2,7 @@ namespace AutopilotMonitor.Shared.Models { /// /// Represents a log file path (or wildcard pattern) to include in the diagnostics ZIP package. - /// Global (built-in) entries are defined by Galactic Admins; tenants may add their own. + /// Global (built-in) entries are defined by Global Admins; tenants may add their own. /// public class DiagnosticsLogPath { @@ -19,7 +19,7 @@ namespace AutopilotMonitor.Shared.Models public string Description { get; set; } /// - /// True when defined globally by a Galactic Admin — displayed as read-only for tenants. + /// True when defined globally by a Global Admin — displayed as read-only for tenants. /// False when added by the tenant itself. /// public bool IsBuiltIn { get; set; } diff --git a/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx b/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx index 3462c234..41f34157 100644 --- a/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/AdminConfigContext.tsx @@ -108,11 +108,11 @@ export function AdminConfigProvider({ children }: { children: React.ReactNode }) const [error, setError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); - const isGalacticAdmin = user?.isGalacticAdmin === true; + const isGlobalAdmin = user?.isGlobalAdmin === true; // Fetch admin configuration useEffect(() => { - if (!isGalacticAdmin) return; + if (!isGlobalAdmin) return; const fetchAdminConfig = async () => { try { @@ -150,11 +150,11 @@ export function AdminConfigProvider({ children }: { children: React.ReactNode }) }; fetchAdminConfig(); - }, [isGalacticAdmin, getAccessToken]); + }, [isGlobalAdmin, getAccessToken]); // Fetch tenants + preview whitelist const fetchTenants = useCallback(async () => { - if (!isGalacticAdmin) return; + if (!isGlobalAdmin) return; try { setLoadingTenants(true); @@ -187,7 +187,7 @@ export function AdminConfigProvider({ children }: { children: React.ReactNode }) } finally { setLoadingTenants(false); } - }, [isGalacticAdmin, getAccessToken]); + }, [isGlobalAdmin, getAccessToken]); useEffect(() => { fetchTenants(); diff --git a/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx b/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx index 29ea44f5..70cda019 100644 --- a/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/AdminPageSections.tsx @@ -76,7 +76,7 @@ export function AdminPageSections() { { id: "software", label: "Software Mapping", href: "/admin/software", group: "Software", groupIcon: }, ], []); - usePageSections(items, "Galactic Admin", "route"); + usePageSections(items, "Global Admin", "route"); return null; } diff --git a/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx index d084ee69..d2f2042b 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx @@ -68,7 +68,7 @@ export function AdminConfigSettingsSection({

Configure default DoS protection limits for all tenants. Normal enrollment generates ~10-30 requests/min.
- Note: Tenants cannot change this value. Only Galactic Admins can override per tenant in tenant management section. + Note: Tenants cannot change this value. Only Global Admins can override per tenant in tenant management section.

{ try { setLoadingAllBlocked(true); - const response = await authenticatedFetch(`${API_BASE_URL}/api/galactic/devices/blocked`, getAccessToken); + const response = await authenticatedFetch(`${API_BASE_URL}/api/global/devices/blocked`, getAccessToken); if (!response.ok) throw new Error(`Failed to load blocked devices: ${response.statusText}`); const data = await response.json(); setBlockedDevices(data.blocked ?? []); diff --git a/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx index 6b163db1..d660d263 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/SessionReportsSection.tsx @@ -80,7 +80,7 @@ export function SessionReportsSection({ setDownloadingBlob(blobName); const res = await authenticatedFetch( - `${API_BASE_URL}/api/galactic/session-reports/download-url?blobName=${encodeURIComponent(blobName)}`, + `${API_BASE_URL}/api/global/session-reports/download-url?blobName=${encodeURIComponent(blobName)}`, getAccessToken ); if (!res.ok) throw new Error(`Failed to get download URL: ${res.statusText}`); @@ -108,7 +108,7 @@ export function SessionReportsSection({ setNoteSaveResult(null); const res = await authenticatedFetch( - `${API_BASE_URL}/api/galactic/session-reports/${selectedReport.reportId}/note`, + `${API_BASE_URL}/api/global/session-reports/${selectedReport.reportId}/note`, getAccessToken, { method: "PATCH", @@ -137,7 +137,7 @@ export function SessionReportsSection({ try { setLoading(true); - const res = await authenticatedFetch(`${API_BASE_URL}/api/galactic/session-reports`, getAccessToken); + const res = await authenticatedFetch(`${API_BASE_URL}/api/global/session-reports`, getAccessToken); if (res.status === 404) { // Table/container doesn't exist yet — no reports submitted so far diff --git a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx index dccf7fc6..10024a7d 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/TenantManagementSection.tsx @@ -587,7 +587,7 @@ export function TenantManagementSection({ ) : (editingTenant.dataRetentionDays < 7 || editingTenant.dataRetentionDays > 180) ? (

⚠ Outside tenant range (7–180) — field will be locked for tenant admins

) : ( -

Tenant range: 7–180. Set 0 for infinite retention. No upper limit for Galactic.

+

Tenant range: 7–180. Set 0 for infinite retention. No upper limit for Global.

)} diff --git a/src/Web/autopilot-monitor-web/app/admin/layout.tsx b/src/Web/autopilot-monitor-web/app/admin/layout.tsx index 645a83e2..bae2e63e 100644 --- a/src/Web/autopilot-monitor-web/app/admin/layout.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/layout.tsx @@ -11,15 +11,15 @@ export default function AdminLayout({ children }: { children: React.ReactNode }) const router = useRouter(); useEffect(() => { - if (user && !user.isGalacticAdmin) { + if (user && !user.isGlobalAdmin) { router.push("/dashboard"); } }, [user, router]); - if (!user?.isGalacticAdmin) return null; + if (!user?.isGlobalAdmin) return null; return ( - + {children} diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx index 5ec7d4f8..1f455845 100644 --- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionAgentMetrics.tsx @@ -113,11 +113,11 @@ export function SectionAgentMetrics() { setError(null); try { - const res = await authenticatedFetch(`${API_BASE_URL}/api/galactic/metrics/platform`, getAccessToken); + const res = await authenticatedFetch(`${API_BASE_URL}/api/global/metrics/platform`, getAccessToken); if (!res.ok) { if (res.status === 403) { - setError('Access denied. Galactic Admin privileges required.'); + setError('Access denied. Global Admin privileges required.'); } else { setError(`Failed to fetch platform metrics: ${res.status}`); } diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx index c6754deb..a8dbed96 100644 --- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionPlatformUsage.tsx @@ -100,8 +100,8 @@ export function SectionPlatformUsage() { } setError(null); - // Platform-wide metrics - cross-tenant (Galactic Admin only) - const response = await authenticatedFetch(`${API_BASE_URL}/api/galactic/metrics/usage`, getAccessToken); + // Platform-wide metrics - cross-tenant (Global Admin only) + const response = await authenticatedFetch(`${API_BASE_URL}/api/global/metrics/usage`, getAccessToken); if (!response.ok) { throw new Error(`Failed to fetch platform usage metrics: ${response.statusText}`); diff --git a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx index 10e67fa5..0ee0ea68 100644 --- a/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/tenants/sections/SectionTenantConfigReport.tsx @@ -321,7 +321,7 @@ export function SectionTenantConfigReport() { // Fetch tenant list useEffect(() => { - if (!user?.isGalacticAdmin) return; + if (!user?.isGlobalAdmin) return; const fetchTenants = async () => { try { setLoadingTenants(true); @@ -349,7 +349,7 @@ export function SectionTenantConfigReport() { } }; fetchTenants(); - }, [user?.isGalacticAdmin, getAccessToken]); + }, [user?.isGlobalAdmin, getAccessToken]); // Fetch config for selected tenant const fetchConfig = useCallback(async () => { @@ -574,7 +574,7 @@ export function SectionTenantConfigReport() { -
+
diff --git a/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx b/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx index 24c49121..3401b00e 100644 --- a/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx +++ b/src/Web/autopilot-monitor-web/app/analyze-rules/page.tsx @@ -71,10 +71,10 @@ export default function AnalyzeRulesPage() { const [togglingRuleId, setTogglingRuleId] = useState(null); const [deletingRuleId, setDeletingRuleId] = useState(null); - // Galactic admin mode - const [galacticAdminMode] = useState(() => { + // Global admin mode + const [globalAdminMode] = useState(() => { if (typeof window !== 'undefined') { - return localStorage.getItem('galacticAdminMode') === 'true'; + return localStorage.getItem('globalAdminMode') === 'true'; } return false; }); @@ -82,7 +82,7 @@ export default function AnalyzeRulesPage() { const [selectedTenantId, setSelectedTenantId] = useState(''); useEffect(() => { - if (!galacticAdminMode || !user?.isGalacticAdmin) return; + if (!globalAdminMode || !user?.isGlobalAdmin) return; const fetchTenants = async () => { try { const response = await authenticatedFetch(`${API_BASE_URL}/api/config/all`, getAccessToken); @@ -104,7 +104,7 @@ export default function AnalyzeRulesPage() { } }; fetchTenants(); - }, [galacticAdminMode, user?.isGalacticAdmin, getAccessToken]); + }, [globalAdminMode, user?.isGlobalAdmin, getAccessToken]); useEffect(() => { if (tenantId && !selectedTenantId) { @@ -112,21 +112,21 @@ export default function AnalyzeRulesPage() { } }, [tenantId]); - const isGalacticOverride = galacticAdminMode && user?.isGalacticAdmin && selectedTenantId && selectedTenantId !== tenantId; - const effectiveTenantId = (galacticAdminMode && user?.isGalacticAdmin && selectedTenantId) ? selectedTenantId : tenantId; - const isReadOnly = !user?.isTenantAdmin && !user?.isGalacticAdmin; + const isGlobalOverride = globalAdminMode && user?.isGlobalAdmin && selectedTenantId && selectedTenantId !== tenantId; + const effectiveTenantId = (globalAdminMode && user?.isGlobalAdmin && selectedTenantId) ? selectedTenantId : tenantId; + const isReadOnly = !user?.isTenantAdmin && !user?.isGlobalAdmin; const fetchRules = useCallback(async () => { if (!effectiveTenantId) return; - const url = isGalacticOverride - ? `${API_BASE_URL}/api/galactic/rules/analyze?tenantId=${effectiveTenantId}` + const url = isGlobalOverride + ? `${API_BASE_URL}/api/global/rules/analyze?tenantId=${effectiveTenantId}` : `${API_BASE_URL}/api/rules/analyze`; await fetchRulesExec( url, undefined, { transform: (d) => { const r = d as { success?: boolean; rules?: AnalyzeRule[] }; return r.success && Array.isArray(r.rules) ? r.rules : []; } } ); - }, [effectiveTenantId, isGalacticOverride, fetchRulesExec]); + }, [effectiveTenantId, isGlobalOverride, fetchRulesExec]); useEffect(() => { fetchRules(); @@ -322,12 +322,12 @@ export default function AnalyzeRulesPage() { return (
- {galacticAdminMode && user?.isGalacticAdmin && ( + {globalAdminMode && user?.isGlobalAdmin && (
- Galactic Admin View + Global Admin View — access to all tenants
)} @@ -341,7 +341,7 @@ export default function AnalyzeRulesPage() {

Manage event analysis rules for issue detection

- {galacticAdminMode && user?.isGalacticAdmin && tenants.length > 0 && ( + {globalAdminMode && user?.isGlobalAdmin && tenants.length > 0 && (
; - user: { isGalacticAdmin?: boolean } | null; + user: { isGlobalAdmin?: boolean } | null; onDeleteSession: (sessionId: string, tenantId: string, deviceName?: string) => void; onBlockDevice: (serialNumber: string, tenantId: string, deviceName?: string) => void; }) { @@ -702,7 +702,7 @@ function SessionCell({ return (
- {galacticAdminMode && user?.isGalacticAdmin && ( + {globalAdminMode && user?.isGlobalAdmin && (
- {/* Galactic Admin Toggle - Only visible to actual galactic admins */} - {user?.isGalacticAdmin && ( + {/* Global Admin Toggle - Only visible to actual global admins */} + {user?.isGlobalAdmin && (
- Galactic Admin - {galacticAdminMode && ACTIVE} + Global Admin + {globalAdminMode && ACTIVE}
- {galacticAdminMode && ( + {globalAdminMode && (

Shows ALL sessions across ALL tenants

diff --git a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx index ecae1e53..bbebdedd 100644 --- a/src/Web/autopilot-monitor-web/app/dashboard/page.tsx +++ b/src/Web/autopilot-monitor-web/app/dashboard/page.tsx @@ -58,9 +58,9 @@ export default function Home() { } return false; }); - const [galacticAdminMode, setGalacticAdminMode] = useState(() => { + const [globalAdminMode, setGlobalAdminMode] = useState(() => { if (typeof window !== 'undefined') { - return localStorage.getItem('galacticAdminMode') === 'true'; + return localStorage.getItem('globalAdminMode') === 'true'; } return false; }); @@ -72,14 +72,14 @@ export default function Home() { // Track if initial fetch has been done to prevent duplicate calls in React StrictMode const hasInitialFetch = useRef(false); - // Track if galactic admin mode has been initialized (to skip initial mount in useEffect) - const hasGalacticModeInitialized = useRef(false); + // Track if global admin mode has been initialized (to skip initial mount in useEffect) + const hasGlobalModeInitialized = useRef(false); // Refs for SignalR handlers to access current filter state (avoids stale closures) const tenantIdFilterRef = useRef(tenantIdFilter); tenantIdFilterRef.current = tenantIdFilter; - const galacticAdminModeRef = useRef(galacticAdminMode); - galacticAdminModeRef.current = galacticAdminMode; + const globalAdminModeRef = useRef(globalAdminMode); + globalAdminModeRef.current = globalAdminMode; const tenantIdRef = useRef(tenantId); tenantIdRef.current = tenantId; @@ -89,12 +89,12 @@ export default function Home() { // Track whether we've been connected at least once — used to detect reconnects const wasConnectedRef = useRef(false); - const fetchSessions = async (loadMoreCursor?: string, galacticTenantIdOverride?: string) => { + const fetchSessions = async (loadMoreCursor?: string, globalTenantIdOverride?: string) => { try { - // Use different endpoint based on galactic admin mode - const effectiveTenantFilter = galacticTenantIdOverride !== undefined ? galacticTenantIdOverride : tenantIdFilter.trim(); - let endpoint = galacticAdminMode - ? `${API_BASE_URL}/api/galactic/sessions${effectiveTenantFilter ? `?tenantId=${encodeURIComponent(effectiveTenantFilter)}` : ''}` + // Use different endpoint based on global admin mode + const effectiveTenantFilter = globalTenantIdOverride !== undefined ? globalTenantIdOverride : tenantIdFilter.trim(); + let endpoint = globalAdminMode + ? `${API_BASE_URL}/api/global/sessions${effectiveTenantFilter ? `?tenantId=${encodeURIComponent(effectiveTenantFilter)}` : ''}` : `${API_BASE_URL}/api/sessions?tenantId=${tenantId}`; // Append cursor for "Load More" requests @@ -143,13 +143,13 @@ export default function Home() { }; const fetchBlockedDevices = async (currentSessions: Session[]) => { - if (!adminMode || !galacticAdminMode) { + if (!adminMode || !globalAdminMode) { setBlockedDevicesSet(new Set()); return; } try { - const tenantIds = galacticAdminMode + const tenantIds = globalAdminMode ? [...new Set(currentSessions.map(s => s.tenantId))] : tenantId ? [tenantId] : []; @@ -186,7 +186,7 @@ export default function Home() { // Redirect regular users (non-admin, non-operator) to progress portal – they must never see the session list useEffect(() => { - if (user && !user.isTenantAdmin && !user.isGalacticAdmin && user.role !== 'Operator') { + if (user && !user.isTenantAdmin && !user.isGlobalAdmin && user.role !== 'Operator') { router.replace("/progress"); } }, [user, router]); @@ -194,7 +194,7 @@ export default function Home() { useEffect(() => { const fetchTenantSecurityConfig = async () => { if (!tenantId) return; - if (user && !user.isTenantAdmin && !user.isGalacticAdmin && user.role !== 'Operator') return; + if (user && !user.isTenantAdmin && !user.isGlobalAdmin && user.role !== 'Operator') return; try { const response = await authenticatedFetch(`${API_BASE_URL}/api/config/${tenantId}`, getAccessToken); @@ -221,10 +221,10 @@ export default function Home() { // Wait for a real tenantId before fetching — TenantContext initializes to '' and // updates asynchronously once AuthContext finishes loading the user token. useEffect(() => { - if (user && !user.isTenantAdmin && !user.isGalacticAdmin && user.role !== 'Operator') { + if (user && !user.isTenantAdmin && !user.isGlobalAdmin && user.role !== 'Operator') { return; // regular users are being redirected, don't fetch } - if (!galacticAdminMode && !tenantId) return; // wait for real tenant ID + if (!globalAdminMode && !tenantId) return; // wait for real tenant ID // Prevent duplicate fetches in React StrictMode (development double-mounting) if (hasInitialFetch.current) { return; @@ -234,7 +234,7 @@ export default function Home() { // Only fetch sessions on load, no automatic health check fetchSessions(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [user, tenantId, galacticAdminMode]); // re-run once user and tenantId are known + }, [user, tenantId, globalAdminMode]); // re-run once user and tenantId are known // Join tenant group when SignalR is connected (for multi-tenancy) useEffect(() => { @@ -266,42 +266,42 @@ export default function Home() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [isConnected, tenantId]); - // Join/leave galactic-admins group when Galactic Admin mode changes + // Join/leave global-admins group when Global Admin mode changes useEffect(() => { if (!isConnected) return; - if (galacticAdminMode) { - console.log('[Home] Galactic Admin mode enabled: joining galactic-admins group'); - joinGroup('galactic-admins'); + if (globalAdminMode) { + console.log('[Home] Global Admin mode enabled: joining global-admins group'); + joinGroup('global-admins'); } else { - console.log('[Home] Galactic Admin mode disabled: leaving galactic-admins group'); - leaveGroup('galactic-admins'); + console.log('[Home] Global Admin mode disabled: leaving global-admins group'); + leaveGroup('global-admins'); } return () => { - // Clean up galactic-admins group on unmount if currently in Galactic Admin mode - if (galacticAdminMode) { - console.log('[Home] Component unmounting: leaving galactic-admins group'); - leaveGroup('galactic-admins'); + // Clean up global-admins group on unmount if currently in Global Admin mode + if (globalAdminMode) { + console.log('[Home] Component unmounting: leaving global-admins group'); + leaveGroup('global-admins'); } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isConnected, galacticAdminMode]); + }, [isConnected, globalAdminMode]); // Setup SignalR listener - re-register when connection changes useEffect(() => { const handleNewSession = (data: { sessionId: string; tenantId: string; session: Session }) => { console.log('New session registered', data); - // In non-galactic mode, only accept sessions from the user's own tenant - if (!galacticAdminModeRef.current && tenantIdRef.current && data.tenantId !== tenantIdRef.current) { - console.log(`Ignoring newSession from tenant ${data.tenantId} (not in galactic mode, own tenant: ${tenantIdRef.current})`); + // In non-global mode, only accept sessions from the user's own tenant + if (!globalAdminModeRef.current && tenantIdRef.current && data.tenantId !== tenantIdRef.current) { + console.log(`Ignoring newSession from tenant ${data.tenantId} (not in global mode, own tenant: ${tenantIdRef.current})`); return; } - // In galactic admin mode with an active tenant filter, ignore sessions from other tenants + // In global admin mode with an active tenant filter, ignore sessions from other tenants const activeFilter = tenantIdFilterRef.current.trim(); - if (galacticAdminModeRef.current && activeFilter && data.tenantId !== activeFilter) { + if (globalAdminModeRef.current && activeFilter && data.tenantId !== activeFilter) { console.log(`Ignoring newSession from tenant ${data.tenantId} (filtered to ${activeFilter})`); return; } @@ -363,25 +363,25 @@ export default function Home() { localStorage.setItem('adminMode', adminMode.toString()); }, [adminMode]); - // Save galactic admin mode to localStorage when it changes + // Save global admin mode to localStorage when it changes useEffect(() => { - localStorage.setItem('galacticAdminMode', galacticAdminMode.toString()); - }, [galacticAdminMode]); + localStorage.setItem('globalAdminMode', globalAdminMode.toString()); + }, [globalAdminMode]); - // Clear blocked devices set when admin mode or galactic admin mode is turned off + // Clear blocked devices set when admin mode or global admin mode is turned off useEffect(() => { - if (!adminMode || !galacticAdminMode) { + if (!adminMode || !globalAdminMode) { setBlockedDevicesSet(new Set()); } - }, [adminMode, galacticAdminMode]); + }, [adminMode, globalAdminMode]); - // Disable galactic admin mode if user is not a galactic admin + // Disable global admin mode if user is not a global admin useEffect(() => { - if (user && !user.isGalacticAdmin && galacticAdminMode) { - console.log('[Home] User is not a galactic admin, disabling galactic admin mode'); - setGalacticAdminMode(false); + if (user && !user.isGlobalAdmin && globalAdminMode) { + console.log('[Home] User is not a global admin, disabling global admin mode'); + setGlobalAdminMode(false); } - }, [user, galacticAdminMode]); + }, [user, globalAdminMode]); // Listen for localStorage changes from other components (e.g., Navbar) useEffect(() => { @@ -389,20 +389,20 @@ export default function Home() { if (e.key === 'adminMode' && e.newValue !== null) { setAdminMode(e.newValue === 'true'); } - if (e.key === 'galacticAdminMode' && e.newValue !== null) { - setGalacticAdminMode(e.newValue === 'true'); + if (e.key === 'globalAdminMode' && e.newValue !== null) { + setGlobalAdminMode(e.newValue === 'true'); } }; const handleCustomStorageChange = () => { const newAdminMode = localStorage.getItem('adminMode') === 'true'; - const newGalacticMode = localStorage.getItem('galacticAdminMode') === 'true'; + const newGlobalMode = localStorage.getItem('globalAdminMode') === 'true'; if (newAdminMode !== adminMode) { setAdminMode(newAdminMode); } - if (newGalacticMode !== galacticAdminMode) { - setGalacticAdminMode(newGalacticMode); + if (newGlobalMode !== globalAdminMode) { + setGlobalAdminMode(newGlobalMode); } }; @@ -413,17 +413,17 @@ export default function Home() { window.removeEventListener('storage', handleStorageChange); window.removeEventListener('localStorageChange', handleCustomStorageChange); }; - }, [adminMode, galacticAdminMode]); + }, [adminMode, globalAdminMode]); - // Refetch sessions when galactic admin mode changes + // Refetch sessions when global admin mode changes useEffect(() => { - if (!hasGalacticModeInitialized.current) { - hasGalacticModeInitialized.current = true; + if (!hasGlobalModeInitialized.current) { + hasGlobalModeInitialized.current = true; return; } - // Clear tenant filter when leaving galactic mode - if (!galacticAdminMode) { + // Clear tenant filter when leaving global mode + if (!globalAdminMode) { setTenantIdFilter(""); } @@ -433,7 +433,7 @@ export default function Home() { setCurrentPage(1); setLoading(true); fetchSessions(); - }, [galacticAdminMode]); + }, [globalAdminMode]); // Reset to page 1 when search query, status filter, sort, or page size changes useEffect(() => { @@ -520,7 +520,7 @@ export default function Home() { tenantId: sessionToBlock.tenantId, serialNumber: sessionToBlock.serialNumber, durationHours: 24, - reason: `Blocked from dashboard by Galactic Admin` + reason: `Blocked from dashboard by Global Admin` }) }); @@ -557,7 +557,7 @@ export default function Home() { // Client-side tenant filter: ensures sessions from other tenants are never displayed, // regardless of how they entered the sessions state (SignalR, race conditions, etc.) - const effectiveSessions = galacticAdminMode + const effectiveSessions = globalAdminMode ? (tenantIdFilter.trim() ? sessions.filter(s => s.tenantId === tenantIdFilter.trim()) : sessions) @@ -805,7 +805,7 @@ export default function Home() { loadingMore={loadingMore} onLoadMore={loadMore} adminMode={adminMode} - galacticAdminMode={galacticAdminMode} + globalAdminMode={globalAdminMode} tenantIdFilter={tenantIdFilter} onTenantIdFilterChange={applyTenantIdFilter} onTenantIdFilterSubmit={submitTenantIdFilter} diff --git a/src/Web/autopilot-monitor-web/app/diagnosis/[sessionId]/page.tsx b/src/Web/autopilot-monitor-web/app/diagnosis/[sessionId]/page.tsx index 7af92eb9..74097e2b 100644 --- a/src/Web/autopilot-monitor-web/app/diagnosis/[sessionId]/page.tsx +++ b/src/Web/autopilot-monitor-web/app/diagnosis/[sessionId]/page.tsx @@ -38,16 +38,16 @@ export default function DiagnosisPage() { const { getAccessToken } = useAuth(); const { addNotification } = useNotifications(); - const [galacticAdminMode] = useState(() => { + const [globalAdminMode] = useState(() => { if (typeof window !== "undefined") { - return localStorage.getItem("galacticAdminMode") === "true"; + return localStorage.getItem("globalAdminMode") === "true"; } return false; }); useEffect(() => { if (!sessionId) return; - if (!galacticAdminMode && !tenantId) return; // wait for real tenant ID + if (!globalAdminMode && !tenantId) return; // wait for real tenant ID sessionIdRef.current = sessionId; if (lastFetchedSessionId.current !== sessionId) { hasInitialFetch.current = false; @@ -57,7 +57,7 @@ export default function DiagnosisPage() { if (hasInitialFetch.current) return; hasInitialFetch.current = true; fetchSessionDetails(); - }, [sessionId, tenantId, galacticAdminMode]); + }, [sessionId, tenantId, globalAdminMode]); useEffect(() => { if (sessionTenantId && sessionId) { @@ -117,8 +117,8 @@ export default function DiagnosisPage() { const fetchSessionDetails = async () => { try { - const endpoint = galacticAdminMode - ? `${API_BASE_URL}/api/galactic/sessions` + const endpoint = globalAdminMode + ? `${API_BASE_URL}/api/global/sessions` : `${API_BASE_URL}/api/sessions?tenantId=${tenantId}`; const response = await authenticatedFetch(endpoint, getAccessToken); if (response.ok) { diff --git a/src/Web/autopilot-monitor-web/app/docs/sections/SectionSettings.tsx b/src/Web/autopilot-monitor-web/app/docs/sections/SectionSettings.tsx index 2be8a973..884fe9d5 100644 --- a/src/Web/autopilot-monitor-web/app/docs/sections/SectionSettings.tsx +++ b/src/Web/autopilot-monitor-web/app/docs/sections/SectionSettings.tsx @@ -227,7 +227,7 @@ export function SectionSettings() { Extra log files or wildcard patterns added to the diagnostics ZIP package. Global paths are defined - platform-wide by the Galactic Admin and always included. Tenant Admins can add their own paths in addition + platform-wide by the Global Admin and always included. Tenant Admins can add their own paths in addition to the global ones (e.g. custom app logs or third-party agent logs). diff --git a/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx b/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx index 54d4030e..a5dc47e2 100644 --- a/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx +++ b/src/Web/autopilot-monitor-web/app/fleet-health/page.tsx @@ -51,20 +51,20 @@ export default function FleetHealthPage() { const { getAccessToken } = useAuth(); const { addNotification } = useNotifications(); - const [galacticAdminMode] = useState(() => { + const [globalAdminMode] = useState(() => { if (typeof window !== "undefined") { - return localStorage.getItem("galacticAdminMode") === "true"; + return localStorage.getItem("globalAdminMode") === "true"; } return false; }); useEffect(() => { - if (!galacticAdminMode && !tenantId) return; // wait for real tenant ID + if (!globalAdminMode && !tenantId) return; // wait for real tenant ID if (hasInitialFetch.current) return; hasInitialFetch.current = true; fetchSessions(); fetchAppMetrics(timeRange); - }, [tenantId, galacticAdminMode]); + }, [tenantId, globalAdminMode]); useEffect(() => { if (isTimeRangeMount.current) { @@ -129,8 +129,8 @@ export default function FleetHealthPage() { const fetchSessions = async () => { try { - const endpoint = galacticAdminMode - ? `${API_BASE_URL}/api/galactic/sessions` + const endpoint = globalAdminMode + ? `${API_BASE_URL}/api/global/sessions` : `${API_BASE_URL}/api/sessions?tenantId=${tenantId}`; const response = await authenticatedFetch(endpoint, getAccessToken); if (response.ok) { @@ -154,8 +154,8 @@ export default function FleetHealthPage() { const fetchAppMetrics = async (range: "7d" | "30d" | "90d" = timeRange) => { try { const days = range === "7d" ? 7 : range === "30d" ? 30 : 90; - const endpoint = galacticAdminMode - ? `${API_BASE_URL}/api/galactic/metrics/app?days=${days}` + const endpoint = globalAdminMode + ? `${API_BASE_URL}/api/global/metrics/app?days=${days}` : `${API_BASE_URL}/api/metrics/app?tenantId=${tenantId}&days=${days}`; const response = await authenticatedFetch(endpoint, getAccessToken); if (response.ok) { @@ -352,12 +352,12 @@ export default function FleetHealthPage() { return (
- {galacticAdminMode && ( + {globalAdminMode && (
- Galactic Admin View + Global Admin View — aggregating data across all tenants
)} diff --git a/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx b/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx index 4b96ed50..7bc25799 100644 --- a/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx +++ b/src/Web/autopilot-monitor-web/app/gather-rules/page.tsx @@ -72,10 +72,10 @@ export default function GatherRulesPage() { // Unrestricted mode (fetched from tenant config for validation indicators) const [unrestrictedMode, setUnrestrictedMode] = useState(false); - // Galactic admin mode - const [galacticAdminMode] = useState(() => { + // Global admin mode + const [globalAdminMode] = useState(() => { if (typeof window !== 'undefined') { - return localStorage.getItem('galacticAdminMode') === 'true'; + return localStorage.getItem('globalAdminMode') === 'true'; } return false; }); @@ -83,7 +83,7 @@ export default function GatherRulesPage() { const [selectedTenantId, setSelectedTenantId] = useState(''); useEffect(() => { - if (!galacticAdminMode || !user?.isGalacticAdmin) return; + if (!globalAdminMode || !user?.isGlobalAdmin) return; const fetchTenants = async () => { try { const response = await authenticatedFetch(`${API_BASE_URL}/api/config/all`, getAccessToken); @@ -105,7 +105,7 @@ export default function GatherRulesPage() { } }; fetchTenants(); - }, [galacticAdminMode, user?.isGalacticAdmin, getAccessToken]); + }, [globalAdminMode, user?.isGlobalAdmin, getAccessToken]); useEffect(() => { if (tenantId && !selectedTenantId) { @@ -113,21 +113,21 @@ export default function GatherRulesPage() { } }, [tenantId]); - const isGalacticOverride = galacticAdminMode && user?.isGalacticAdmin && selectedTenantId && selectedTenantId !== tenantId; - const effectiveTenantId = (galacticAdminMode && user?.isGalacticAdmin && selectedTenantId) ? selectedTenantId : tenantId; - const isReadOnly = !user?.isTenantAdmin && !user?.isGalacticAdmin; + const isGlobalOverride = globalAdminMode && user?.isGlobalAdmin && selectedTenantId && selectedTenantId !== tenantId; + const effectiveTenantId = (globalAdminMode && user?.isGlobalAdmin && selectedTenantId) ? selectedTenantId : tenantId; + const isReadOnly = !user?.isTenantAdmin && !user?.isGlobalAdmin; const fetchRules = useCallback(async () => { if (!effectiveTenantId) return; - const url = isGalacticOverride - ? `${API_BASE_URL}/api/galactic/rules/gather?tenantId=${effectiveTenantId}` + const url = isGlobalOverride + ? `${API_BASE_URL}/api/global/rules/gather?tenantId=${effectiveTenantId}` : `${API_BASE_URL}/api/rules/gather?tenantId=${effectiveTenantId}`; await fetchRulesExec( url, undefined, { transform: (d) => (d as { rules?: GatherRule[] }).rules || [] } ); - }, [effectiveTenantId, isGalacticOverride, fetchRulesExec]); + }, [effectiveTenantId, isGlobalOverride, fetchRulesExec]); useEffect(() => { if (effectiveTenantId) { @@ -140,8 +140,8 @@ export default function GatherRulesPage() { if (!effectiveTenantId) return; const fetchConfig = async () => { try { - const url = isGalacticOverride - ? `${API_BASE_URL}/api/galactic/config/${effectiveTenantId}` + const url = isGlobalOverride + ? `${API_BASE_URL}/api/global/config/${effectiveTenantId}` : `${API_BASE_URL}/api/config/${effectiveTenantId}`; const response = await authenticatedFetch(url, getAccessToken); if (response.ok) { @@ -153,7 +153,7 @@ export default function GatherRulesPage() { } }; fetchConfig(); - }, [effectiveTenantId, isGalacticOverride, getAccessToken]); + }, [effectiveTenantId, isGlobalOverride, getAccessToken]); const handleToggleRule = async (rule: GatherRule) => { setTogglingRule(rule.ruleId); @@ -395,12 +395,12 @@ export default function GatherRulesPage() { return (
- {galacticAdminMode && user?.isGalacticAdmin && ( + {globalAdminMode && user?.isGlobalAdmin && (
- Galactic Admin View + Global Admin View — access to all tenants
)} @@ -414,7 +414,7 @@ export default function GatherRulesPage() {

Manage data collection rules for device enrollment

- {galacticAdminMode && user?.isGalacticAdmin && tenants.length > 0 && ( + {globalAdminMode && user?.isGlobalAdmin && tenants.length > 0 && (
{ - // Tenant metrics are always accessible - no galactic admin check needed + // Tenant metrics are always accessible - no global admin check needed fetchMetrics(); }, [router]); diff --git a/src/Web/autopilot-monitor-web/components/AppInsightsInit.tsx b/src/Web/autopilot-monitor-web/components/AppInsightsInit.tsx index 0fe096d9..e849e1f8 100644 --- a/src/Web/autopilot-monitor-web/components/AppInsightsInit.tsx +++ b/src/Web/autopilot-monitor-web/components/AppInsightsInit.tsx @@ -22,7 +22,7 @@ export default function AppInsightsInit() { setTelemetryContext( tenantId || null, user?.isTenantAdmin ?? false, - user?.isGalacticAdmin ?? false, + user?.isGlobalAdmin ?? false, theme ); }, [tenantId, user, theme]); diff --git a/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx b/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx index c32234fe..e3b35cc8 100644 --- a/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx +++ b/src/Web/autopilot-monitor-web/components/GlobalSidebar.tsx @@ -45,11 +45,11 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { return () => mql.removeEventListener("change", handler); }, []); - // Galactic admin mode from localStorage (same pattern as Navbar) - const [galacticAdminMode, setGalacticAdminMode] = useState(false); + // Global admin mode from localStorage (same pattern as Navbar) + const [globalAdminMode, setGlobalAdminMode] = useState(false); useEffect(() => { if (typeof window === "undefined") return; - const read = () => setGalacticAdminMode(localStorage.getItem("galacticAdminMode") === "true"); + const read = () => setGlobalAdminMode(localStorage.getItem("globalAdminMode") === "true"); read(); window.addEventListener("localStorageChange", read); window.addEventListener("storage", read); @@ -174,13 +174,13 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { const isTenantAdmin = user?.isTenantAdmin ?? false; const isOperator = user?.role === "Operator"; const isAdminOrOperator = isTenantAdmin || isOperator; - const isGalacticAdmin = user?.isGalacticAdmin ?? false; + const isGlobalAdmin = user?.isGlobalAdmin ?? false; const isGroupVisible = (group: NavGroup | ExpandableNavGroup): boolean => { switch (group.visibility) { case "all": return true; case "adminOrOperator": return isAdminOrOperator; - case "galacticAdmin": return isGalacticAdmin && galacticAdminMode; + case "globalAdmin": return isGlobalAdmin && globalAdminMode; default: return false; } }; @@ -240,21 +240,21 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { }; // Shared item classes - const itemClass = (active: boolean, galactic = false) => { + const itemClass = (active: boolean, isGlobal = false) => { if (active) { - return galactic + return isGlobal ? "bg-purple-50 text-purple-700 font-semibold dark:bg-purple-900/30 dark:text-purple-300" : "bg-blue-50 text-blue-700 font-semibold dark:bg-blue-900/30 dark:text-blue-300"; } - return galactic + return isGlobal ? "text-purple-600 hover:bg-purple-50 hover:text-purple-800 dark:text-purple-400 dark:hover:bg-purple-900/20 dark:hover:text-purple-300" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200"; }; // --- Render a global nav link --- - const renderGlobalItem = (item: NavItem, galactic = false) => { + const renderGlobalItem = (item: NavItem, isGlobal = false) => { const active = isNavActive(item.href); - const base = `flex items-center gap-2.5 rounded-md text-sm transition-colors ${itemClass(active, galactic)}`; + const base = `flex items-center gap-2.5 rounded-md text-sm transition-colors ${itemClass(active, isGlobal)}`; if (collapseState === "icons") { return ( @@ -346,7 +346,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { const hasPageSections = pageSections.length > 0; // Regular users see minimal nav - const isRegularUser = !isAdminOrOperator && !isGalacticAdmin; + const isRegularUser = !isAdminOrOperator && !isGlobalAdmin; const renderNavContent = (isMobile = false) => ( <> @@ -368,7 +368,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) {
{(collapseState === "full" || isMobile) && (

@@ -379,18 +379,18 @@ export function GlobalSidebar({ children }: { children: ReactNode }) {


)}
    - {group.items.map((item) => renderGlobalItem(item, group.style === "galactic"))} + {group.items.map((item) => renderGlobalItem(item, group.style === "global"))}
))} - {/* Expandable groups (GitHub-style) — Configuration, Galactic Admin */} + {/* Expandable groups (GitHub-style) — Configuration, Global Admin */} {!isRegularUser && visibleExpandableGroups.map((group) => (
{/* Group label */} {(collapseState === "full" || isMobile) && (

@@ -399,7 +399,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { )} {collapseState === "icons" && !isMobile && (


@@ -409,7 +409,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { const isExpanded = expandedGroups.has(expandItem.id); const itemHasActive = expandItem.items.some((sub) => pathname === sub.href || pathname.startsWith(sub.href + "/")); const firstHref = expandItem.items[0]?.href ?? "#"; - const isGalactic = group.style === "galactic"; + const isGlobalStyle = group.style === "global"; if (collapseState === "icons" && !isMobile) { // Icons mode: show group icon as link @@ -420,10 +420,10 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { onClick={() => setMobileDrawerOpen(false)} className={`flex items-center justify-center px-2 py-2 rounded-md text-sm transition-colors relative group ${ itemHasActive - ? isGalactic + ? isGlobalStyle ? "bg-purple-50 text-purple-700 font-semibold dark:bg-purple-900/30 dark:text-purple-300" : "bg-blue-50 text-blue-700 font-semibold dark:bg-blue-900/30 dark:text-blue-300" - : isGalactic + : isGlobalStyle ? "text-purple-600 hover:bg-purple-50 hover:text-purple-800 dark:text-purple-400 dark:hover:bg-purple-900/20" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200" }`} @@ -445,10 +445,10 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { onClick={() => toggleGroup(expandItem.id)} className={`w-full flex items-center gap-2.5 px-3 py-1.5 rounded-md text-sm transition-colors ${ itemHasActive - ? isGalactic + ? isGlobalStyle ? "text-purple-700 font-semibold dark:text-purple-300" : "text-blue-700 font-semibold dark:text-blue-300" - : isGalactic + : isGlobalStyle ? "text-purple-600 hover:bg-purple-50 hover:text-purple-800 dark:text-purple-400 dark:hover:bg-purple-900/20" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200" }`} @@ -473,7 +473,7 @@ export function GlobalSidebar({ children }: { children: ReactNode }) { onClick={() => setMobileDrawerOpen(false)} className={`block pl-10 pr-3 py-1 rounded-md text-[13px] transition-colors ${ subActive - ? isGalactic + ? isGlobalStyle ? "bg-purple-50 text-purple-700 font-medium dark:bg-purple-900/30 dark:text-purple-300" : "bg-blue-50 text-blue-700 font-medium dark:bg-blue-900/30 dark:text-blue-300" : "text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200" diff --git a/src/Web/autopilot-monitor-web/components/Navbar.tsx b/src/Web/autopilot-monitor-web/components/Navbar.tsx index 43debd08..187a78ff 100644 --- a/src/Web/autopilot-monitor-web/components/Navbar.tsx +++ b/src/Web/autopilot-monitor-web/components/Navbar.tsx @@ -2,7 +2,7 @@ import { useAuth } from '@/contexts/AuthContext'; import { useNotifications } from '@/contexts/NotificationContext'; -import { useGalacticNotifications } from '@/contexts/GalacticNotificationContext'; +import { useGlobalNotifications } from '@/contexts/GlobalNotificationContext'; import { useTheme } from '@/contexts/ThemeContext'; import { useState, useRef, useEffect } from 'react'; import Link from 'next/link'; @@ -13,7 +13,7 @@ import { trackEvent } from '@/lib/appInsights'; export default function Navbar() { const { isAuthenticated, user, logout } = useAuth(); const { notifications, unreadCount, markAsRead, markAllAsRead, removeNotification, clearAll } = useNotifications(); - const { notifications: galacticNotifications, dismissNotification: dismissGalactic, dismissAll: dismissAllGalactic } = useGalacticNotifications(); + const { notifications: globalNotifications, dismissNotification: dismissGlobal, dismissAll: dismissAllGlobal } = useGlobalNotifications(); const { theme, toggleTheme } = useTheme(); const pathname = usePathname(); @@ -27,9 +27,9 @@ export default function Navbar() { } return false; }); - const [galacticAdminMode, setGalacticAdminMode] = useState(() => { + const [globalAdminMode, setGlobalAdminMode] = useState(() => { if (typeof window !== 'undefined') { - return localStorage.getItem('galacticAdminMode') === 'true'; + return localStorage.getItem('globalAdminMode') === 'true'; } return false; }); @@ -55,10 +55,10 @@ export default function Navbar() { useEffect(() => { if (typeof window !== 'undefined') { - localStorage.setItem('galacticAdminMode', galacticAdminMode.toString()); + localStorage.setItem('globalAdminMode', globalAdminMode.toString()); window.dispatchEvent(new Event('localStorageChange')); } - }, [galacticAdminMode]); + }, [globalAdminMode]); useEffect(() => { if (typeof window !== 'undefined') { @@ -163,7 +163,7 @@ export default function Navbar() { const isAdminOrOperator = isTenantAdmin || isOperator; // Regular users (non-Admin, non-Operator): show minimal navbar with only Progress Portal - if (!isAdminOrOperator && !user?.isGalacticAdmin) { + if (!isAdminOrOperator && !user?.isGlobalAdmin) { return (