diff --git a/src/ScadaLink.AuditLog/Payload/IAuditPayloadFilter.cs b/src/ScadaLink.AuditLog/Payload/IAuditPayloadFilter.cs
new file mode 100644
index 0000000..45b7ee2
--- /dev/null
+++ b/src/ScadaLink.AuditLog/Payload/IAuditPayloadFilter.cs
@@ -0,0 +1,30 @@
+using ScadaLink.Commons.Entities.Audit;
+
+namespace ScadaLink.AuditLog.Payload;
+
+///
+/// Filters an between construction and persistence —
+/// truncates oversized payload fields, applies header/body/SQL-parameter
+/// redaction, sets .
+///
+///
+///
+/// Pure function: returns a filtered COPY of the input via with
+/// expressions; never throws (over-redacts on internal failure and increments
+/// the AuditRedactionFailure health metric).
+///
+///
+/// Wired in M5 between event construction and the writer chain
+/// (FallbackAuditWriter.WriteAsync, CentralAuditWriter.WriteAsync,
+/// and the AuditLogIngestActor handlers).
+///
+///
+public interface IAuditPayloadFilter
+{
+ ///
+ /// Apply the configured truncation + redaction policy to
+ /// and return a filtered copy. MUST NOT throw — on internal failure, over-redact
+ /// and surface the failure via the audit-redaction-failure health metric.
+ ///
+ AuditEvent Apply(AuditEvent rawEvent);
+}
diff --git a/tests/ScadaLink.AuditLog.Tests/Payload/PayloadFilterContractTests.cs b/tests/ScadaLink.AuditLog.Tests/Payload/PayloadFilterContractTests.cs
new file mode 100644
index 0000000..6848b29
--- /dev/null
+++ b/tests/ScadaLink.AuditLog.Tests/Payload/PayloadFilterContractTests.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Reflection;
+using ScadaLink.AuditLog.Payload;
+using ScadaLink.Commons.Entities.Audit;
+
+namespace ScadaLink.AuditLog.Tests.Payload;
+
+///
+/// Bundle A (M5-T1) contract test for . The
+/// interface is the seam between event construction and writer persistence;
+/// later bundles register the production implementation as a singleton and
+/// invoke it from the site/central writer paths. We pin the surface area here
+/// via reflection so accidental signature drift breaks the build before the
+/// downstream wiring goes red.
+///
+public class PayloadFilterContractTests
+{
+ [Fact]
+ public void Interface_Exists_InPayloadNamespace()
+ {
+ var type = typeof(IAuditPayloadFilter);
+
+ Assert.True(type.IsInterface, "IAuditPayloadFilter must be an interface");
+ Assert.Equal("ScadaLink.AuditLog.Payload", type.Namespace);
+ }
+
+ [Fact]
+ public void Apply_Method_HasDocumentedSignature()
+ {
+ var type = typeof(IAuditPayloadFilter);
+
+ var method = type.GetMethod(
+ "Apply",
+ BindingFlags.Instance | BindingFlags.Public,
+ binder: null,
+ types: new[] { typeof(AuditEvent) },
+ modifiers: null);
+
+ Assert.NotNull(method);
+ Assert.Equal(typeof(AuditEvent), method!.ReturnType);
+
+ var parameters = method.GetParameters();
+ Assert.Single(parameters);
+ Assert.Equal("rawEvent", parameters[0].Name);
+ Assert.Equal(typeof(AuditEvent), parameters[0].ParameterType);
+ }
+
+ [Fact]
+ public void Interface_DeclaresExactlyOneMethod()
+ {
+ var type = typeof(IAuditPayloadFilter);
+ var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
+ .Where(m => !m.IsSpecialName)
+ .ToArray();
+
+ Assert.Single(methods);
+ Assert.Equal("Apply", methods[0].Name);
+ }
+}