diff --git a/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor b/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor
index 8c53f702..24d529ab 100644
--- a/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor
+++ b/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor
@@ -7,18 +7,28 @@
@if (this.ShowAcceptanceMetadata)
{
- @if (this.Acceptance is null)
+ @if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.MISSING)
{
@T("This mandatory info has not been accepted yet.")
}
- else if (!string.Equals(this.Acceptance.AcceptedVersion, this.Info.VersionText, StringComparison.Ordinal))
+ else if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.VERSION_CHANGED)
{
- @T("The current version has not been accepted yet.")
+ @T("A new version of the terms is available. Please review it again.")
- @T("Last accepted version"): @this.Acceptance.AcceptedVersion
+ @T("Last accepted version"): @this.Acceptance!.AcceptedVersion
+
+ @T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
+
+ }
+ else if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.CONTENT_CHANGED)
+ {
+
+ @T("Please review this text again. The content was changed.")
+
+ @T("Last accepted version"): @this.Acceptance!.AcceptedVersion
@T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
@@ -26,7 +36,7 @@
else
{
- @T("Accepted version"): @this.Acceptance.AcceptedVersion
+ @T("Accepted version"): @this.Acceptance!.AcceptedVersion
@T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
diff --git a/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor.cs b/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor.cs
index fa69c994..a9d97cde 100644
--- a/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor.cs
+++ b/app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor.cs
@@ -6,6 +6,14 @@ namespace AIStudio.Components;
public partial class MandatoryInfoDisplay
{
+ private enum MandatoryInfoAcceptanceStatus
+ {
+ MISSING,
+ VERSION_CHANGED,
+ CONTENT_CHANGED,
+ ACCEPTED,
+ }
+
[Parameter]
public DataMandatoryInfo Info { get; set; } = new();
@@ -14,4 +22,21 @@ public partial class MandatoryInfoDisplay
[Parameter]
public bool ShowAcceptanceMetadata { get; set; }
+
+ private MandatoryInfoAcceptanceStatus AcceptanceStatus
+ {
+ get
+ {
+ if (this.Acceptance is null)
+ return MandatoryInfoAcceptanceStatus.MISSING;
+
+ if (!string.Equals(this.Acceptance.AcceptedVersion, this.Info.VersionText, StringComparison.Ordinal))
+ return MandatoryInfoAcceptanceStatus.VERSION_CHANGED;
+
+ if (!string.Equals(this.Acceptance.AcceptedHash, this.Info.GetAcceptanceHash(), StringComparison.Ordinal))
+ return MandatoryInfoAcceptanceStatus.CONTENT_CHANGED;
+
+ return MandatoryInfoAcceptanceStatus.ACCEPTED;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Layout/MainLayout.razor.cs b/app/MindWork AI Studio/Layout/MainLayout.razor.cs
index da13385d..3d8d6b2a 100644
--- a/app/MindWork AI Studio/Layout/MainLayout.razor.cs
+++ b/app/MindWork AI Studio/Layout/MainLayout.razor.cs
@@ -418,7 +418,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
.Where(info =>
{
var acceptance = this.SettingsManager.ConfigurationData.MandatoryInformation.FindAcceptance(info.Id);
- return acceptance is null || acceptance.AcceptedVersion != info.VersionText;
+ return acceptance is null || !string.Equals(acceptance.AcceptedHash, info.GetAcceptanceHash(), StringComparison.Ordinal);
});
}
@@ -441,6 +441,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
{
InfoId = info.Id,
AcceptedVersion = info.VersionText,
+ AcceptedHash = info.GetAcceptanceHash(),
AcceptedAtUtc = DateTimeOffset.UtcNow,
EnterpriseConfigurationPluginId = info.EnterpriseConfigurationPluginId,
};
diff --git a/app/MindWork AI Studio/Plugins/configuration/plugin.lua b/app/MindWork AI Studio/Plugins/configuration/plugin.lua
index 3faa4c82..552d6462 100644
--- a/app/MindWork AI Studio/Plugins/configuration/plugin.lua
+++ b/app/MindWork AI Studio/Plugins/configuration/plugin.lua
@@ -267,6 +267,8 @@ CONFIG["CHAT_TEMPLATES"] = {}
CONFIG["DOCUMENT_ANALYSIS_POLICIES"] = {}
-- Mandatory infos that users must explicitly accept before using AI Studio:
+-- AI Studio asks users again when Version, Title, or Markdown change.
+-- Changing Version additionally allows the UI to communicate that a new version is available.
CONFIG["MANDATORY_INFOS"] = {}
-- An example mandatory info:
diff --git a/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfo.cs b/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfo.cs
index 167f9dc3..a633e2d3 100644
--- a/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfo.cs
+++ b/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfo.cs
@@ -1,3 +1,6 @@
+using System.Security.Cryptography;
+using System.Text;
+
using Lua;
namespace AIStudio.Settings.DataModel;
@@ -22,7 +25,8 @@ public sealed record DataMandatoryInfo
public string Title { get; private init; } = string.Empty;
///
- /// The configured version string. When it changes, the user must accept the text again.
+ /// The configured version string shown to the user. A changed version triggers re-acceptance
+ /// and allows the UI to distinguish a new version from a content-only change.
///
public string VersionText { get; private init; } = string.Empty;
@@ -41,6 +45,13 @@ public sealed record DataMandatoryInfo
///
public string RejectButtonText { get; private init; } = string.Empty;
+ public string GetAcceptanceHash()
+ {
+ var content = $"Version:{this.VersionText}\nTitle:{this.Title}\nMarkdown:{this.Markdown}";
+ var hash = SHA256.HashData(Encoding.UTF8.GetBytes(content));
+ return Convert.ToHexString(hash);
+ }
+
public static bool TryParseConfiguration(int idx, LuaTable table, Guid configPluginId, out DataMandatoryInfo mandatoryInfo)
{
mandatoryInfo = new DataMandatoryInfo();
diff --git a/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfoAcceptance.cs b/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfoAcceptance.cs
index 765816c7..e24969d0 100644
--- a/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfoAcceptance.cs
+++ b/app/MindWork AI Studio/Settings/DataModel/DataMandatoryInfoAcceptance.cs
@@ -12,6 +12,11 @@ public sealed record DataMandatoryInfoAcceptance
///
public string AcceptedVersion { get; init; } = string.Empty;
+ ///
+ /// The accepted hash of the mandatory info content.
+ ///
+ public string AcceptedHash { get; init; } = string.Empty;
+
///
/// The UTC time of the acceptance.
///