diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs
index 0f18913e..67f24aac 100644
--- a/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs
+++ b/src/Backend/AutopilotMonitor.Functions.Tests/EndpointPolicyCatalogCompletenessTests.cs
@@ -174,6 +174,23 @@ public class EndpointPolicyCatalogCompletenessTests
Assert.Equal(EndpointPolicy.TenantAdminOrGA, postRules.Policy);
}
+ ///
+ /// IME log pattern edits write GLOBAL patterns (all tenants) and the handler has no GA
+ /// re-gate, so the PUT must stay GlobalAdminOnly — a downgrade to TenantAdminOrGA would let
+ /// any customer tenant admin mutate platform-wide patterns via ?global=true.
+ ///
+ [Fact]
+ public void ImeLogPatternWrites_AreGlobalAdminOnly()
+ {
+ var putPattern = EndpointAccessPolicyCatalog.FindPolicy("PUT", "/api/rules/ime-log-patterns/IME-001");
+ var reseed = EndpointAccessPolicyCatalog.FindPolicy("POST", "/api/rules/ime-log-patterns/reseed");
+
+ Assert.NotNull(putPattern);
+ Assert.NotNull(reseed);
+ Assert.Equal(EndpointPolicy.GlobalAdminOnly, putPattern.Policy);
+ Assert.Equal(EndpointPolicy.GlobalAdminOnly, reseed.Policy);
+ }
+
///
/// Unregistered routes must return null (fail-closed).
///
diff --git a/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs b/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs
index 2630e84f..fb507068 100644
--- a/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs
+++ b/src/Backend/AutopilotMonitor.Functions/Security/EndpointAccessPolicyCatalog.cs
@@ -311,7 +311,6 @@ public static class EndpointAccessPolicyCatalog
new("POST", "rules/analyze/{ruleId}/create-from-template", EndpointPolicy.TenantAdminOrGA),
new("PUT", "rules/analyze/{ruleId}", EndpointPolicy.TenantAdminOrGA),
new("DELETE", "rules/analyze/{ruleId}", EndpointPolicy.TenantAdminOrGA),
- new("PUT", "rules/ime-log-patterns/{patternId}", EndpointPolicy.TenantAdminOrGA),
new("POST", "sessions/{sessionId}/mark-failed", EndpointPolicy.TenantAdminOrGA),
new("POST", "sessions/{sessionId}/mark-succeeded", EndpointPolicy.TenantAdminOrGA),
// Operator tier so troubleshooting staff can queue request_diagnostics ("Collect Logs" in
@@ -541,6 +540,9 @@ public static class EndpointAccessPolicyCatalog
new("GET", "vulnerability/ignored-software", EndpointPolicy.GlobalReadOrAdmin),
new("POST", "vulnerability/ignored-software", EndpointPolicy.GlobalAdminOnly),
new("DELETE", "vulnerability/ignored-software", EndpointPolicy.GlobalAdminOnly),
+ // Both routes mutate GLOBAL patterns (all tenants); there is no tenant-scoped variant yet,
+ // so PUT must not sit on the TenantAdminOrGA tier — the handler has no GA re-gate.
+ new("PUT", "rules/ime-log-patterns/{patternId}", EndpointPolicy.GlobalAdminOnly),
new("POST", "rules/ime-log-patterns/reseed", EndpointPolicy.GlobalAdminOnly),
new("GET", "global/mcp-users", EndpointPolicy.GlobalReadOrAdmin),
new("POST", "global/mcp-users", EndpointPolicy.GlobalAdminOnly),