diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor
index 1c90f954..d2dbfea9 100644
--- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor
+++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/ConfigurationAuditLog.razor
@@ -4,6 +4,7 @@
@using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit
@using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories
@attribute [Authorize(Policy = AuthorizationPolicies.OperationalAudit)]
+@implements IAsyncDisposable
@inject ICentralUiRepository CentralUiRepository
@inject NavigationManager Nav
@inject IJSRuntime JS
@@ -286,6 +287,19 @@
private const string BrowserTimeModulePath = "./_content/ZB.MOM.WW.ScadaBridge.CentralUI/js/browser-time.js";
private IJSObjectReference? _browserTimeModule;
+ ///
+ /// Releases the dynamically imported browser-time module so its JS-side object reference
+ /// is not retained for the life of the circuit. A disconnected circuit has already
+ /// dropped it, so that failure is expected and swallowed.
+ ///
+ public async ValueTask DisposeAsync()
+ {
+ if (_browserTimeModule is null) return;
+ try { await _browserTimeModule.DisposeAsync(); }
+ catch (JSDisconnectedException) { /* circuit already gone */ }
+ _browserTimeModule = null;
+ }
+
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Audit/ConfigurationAuditLogDisposeTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Audit/ConfigurationAuditLogDisposeTests.cs
new file mode 100644
index 00000000..1df3eb62
--- /dev/null
+++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Audit/ConfigurationAuditLogDisposeTests.cs
@@ -0,0 +1,60 @@
+using System.Security.Claims;
+using Bunit;
+using Microsoft.AspNetCore.Components.Authorization;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.JSInterop;
+using NSubstitute;
+using ZB.MOM.WW.ScadaBridge.CentralUI.Auth;
+using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
+using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
+using AuditLogPage = ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Audit.ConfigurationAuditLog;
+
+namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Audit;
+
+/// Review 2026-10-21 07/M-1: the browser-time JS module must be disposed with the page.
+public class ConfigurationAuditLogDisposeTests : BunitContext
+{
+ private sealed class StubAuth(AuthenticationState state) : AuthenticationStateProvider
+ {
+ public override Task GetAuthenticationStateAsync() => Task.FromResult(state);
+ }
+
+ private (IJSObjectReference module, IRenderedComponent cut) Arrange(bool moduleThrowsOnDispose)
+ {
+ var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "u") }, "T");
+ var auth = new StubAuth(new AuthenticationState(new ClaimsPrincipal(identity)));
+ Services.AddSingleton(auth);
+ Services.AddScoped(_ => new SiteScopeService(auth));
+ Services.AddScoped();
+ Services.AddSingleton(Substitute.For());
+
+ var module = Substitute.For();
+ module.InvokeAsync("getTimezoneOffsetMinutes", Arg.Any