diff --git a/.claude/commands b/.claude/commands
index 8dcfe1e2..80ee4efa 160000
--- a/.claude/commands
+++ b/.claude/commands
@@ -1 +1 @@
-Subproject commit 8dcfe1e23e5520ca373caf4afca257d3a1a67d9b
+Subproject commit 80ee4efaf6066b0b720b8d6a498c3586b61d504c
diff --git a/internal b/internal
index 33acedeb..8efdea43 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 33acedeb8514afc90d5f1a0cb7bb5359e08e6174
+Subproject commit 8efdea43fab477dce8cce1abde9ccc7bfe5921a8
diff --git a/rules/analyze/ANALYZE-ID-001.json b/rules/analyze/ANALYZE-ID-001.json
index 6da3acd5..389b60a1 100644
--- a/rules/analyze/ANALYZE-ID-001.json
+++ b/rules/analyze/ANALYZE-ID-001.json
@@ -5,6 +5,7 @@
"description": "Detects when a certificate with the configured subject is missing from the local machine personal store (LocalMachine\\My). Requires the gather rule GATHER-ID-002 (machine cert store inventory) to be enabled — the check runs against its gather_machine_cert_store output. A missing certificate may indicate that MDM enrollment certificate provisioning or SCEP certificate deployment failed.",
"severity": "warning",
"category": "identity",
+ "author": "Community",
"isCommunity": true,
"enabled": false,
"evaluateOn": [
diff --git a/rules/dist/analyze-rules.json b/rules/dist/analyze-rules.json
index 409c4642..ab52e2ee 100644
--- a/rules/dist/analyze-rules.json
+++ b/rules/dist/analyze-rules.json
@@ -2806,6 +2806,7 @@
"description": "Detects when a certificate with the configured subject is missing from the local machine personal store (LocalMachine\\My). Requires the gather rule GATHER-ID-002 (machine cert store inventory) to be enabled — the check runs against its gather_machine_cert_store output. A missing certificate may indicate that MDM enrollment certificate provisioning or SCEP certificate deployment failed.",
"severity": "warning",
"category": "identity",
+ "author": "Community",
"isCommunity": true,
"enabled": false,
"evaluateOn": [
diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/AnalyzeRulesFunctionAuthorEndpointTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/AnalyzeRulesFunctionAuthorEndpointTests.cs
new file mode 100644
index 00000000..1276f3cd
--- /dev/null
+++ b/src/Backend/AutopilotMonitor.Functions.Tests/AnalyzeRulesFunctionAuthorEndpointTests.cs
@@ -0,0 +1,206 @@
+using System.Net;
+using System.Security.Claims;
+using System.Text;
+using AutopilotMonitor.Functions.Functions.Rules;
+using AutopilotMonitor.Functions.Helpers;
+using AutopilotMonitor.Functions.Services;
+using AutopilotMonitor.Shared.DataAccess;
+using AutopilotMonitor.Shared.Models;
+using Azure.Core.Serialization;
+using Microsoft.Azure.Functions.Worker;
+using Microsoft.Azure.Functions.Worker.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging.Abstractions;
+using Moq;
+using Newtonsoft.Json;
+
+namespace AutopilotMonitor.Functions.Tests;
+
+///
+/// Analyze twin of : the rule Author is
+/// stamped from the caller's JWT on create, on a PUT-upsert of an unknown rule and on the
+/// template copy, and a true update keeps the original creator over editor and body.
+/// Before this pin, custom analyze rules were created as "Autopilot Monitor" and the edit
+/// path let the browser choose the author.
+///
+public class AnalyzeRulesFunctionAuthorEndpointTests
+{
+ private const string TenantId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
+ private const string RuleId = "ANALYZE-CUSTOM-777";
+ private const string TemplateRuleId = "ANALYZE-SEC-004";
+
+ private sealed class FakeHttpResponseData : HttpResponseData
+ {
+ public FakeHttpResponseData(FunctionContext context) : base(context) { }
+ public override HttpStatusCode StatusCode { get; set; } = HttpStatusCode.OK;
+ public override HttpHeadersCollection Headers { get; set; } = new();
+ public override Stream Body { get; set; } = new MemoryStream();
+ public override HttpCookies Cookies { get; } = new Mock().Object;
+ }
+
+ private static FunctionContext BuildContext(ClaimsPrincipal? principal)
+ {
+ var services = new ServiceCollection();
+ services.AddOptions();
+ services.Configure(o => o.Serializer =
+ new JsonObjectSerializer(ApiJsonOptions.Create()));
+ var provider = services.BuildServiceProvider();
+
+ var items = new Dictionary