Create `ember-compatibility-functions.h` to represent what `ember-compatibility-functions.cpp` contains (#32623)

* Create a ember-compatibility-functions header to define what the cpp contains

* Fix includes of ember compatibility functions

* Fix lint

* Restyle

* Remove reporting.h since that actually declares what ember-compatibility-functions.cpp implements

* Revert "Remove reporting.h since that actually declares what ember-compatibility-functions.cpp implements"

This reverts commit 297f526359fbc7a8fd57b58335faf033bedeaf2e.

* Move the reporting bits into reporting.cpp

* Restyle

* Remove some unused includes

* Add reporting.cpp to cmake builds

* Fix rpc builds with new includes

* Fix oven and java matter controller compilation

* Some additional minor comments for the dynamic dispatcher ... unfortunately deps seem a bit strict

* Restyle

* Add reporting.cpp to the list of know issues (it is the same as ember-compatibility-functions)

* Add reporting.cpp to xcode

* Fix darwin compile

* Remove extra comment based on code review

* Comment rephrase

---------

Co-authored-by: Andrei Litvin <andreilitvin@google.com>
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 15d0d3e..59c0d4e 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -97,6 +97,7 @@
                      --known-failure app/CommandSenderLegacyCallback.h \
                      --known-failure app/data-model/ListLargeSystemExtensions.h \
                      --known-failure app/ReadHandler.h \
+                     --known-failure app/reporting/reporting.cpp \
                      --known-failure app/reporting/tests/MockReportScheduler.cpp \
                      --known-failure app/reporting/tests/MockReportScheduler.h \
                      --known-failure app/TestEventTriggerDelegate.h \
@@ -111,6 +112,7 @@
                      --known-failure app/util/DataModelHandler.cpp \
                      --known-failure app/util/DataModelHandler.h \
                      --known-failure app/util/ember-compatibility-functions.cpp \
+                     --known-failure app/util/ember-compatibility-functions.h \
                      --known-failure app/util/endpoint-config-api.h \
                      --known-failure app/util/generic-callbacks.h \
                      --known-failure app/util/generic-callback-stubs.cpp \
diff --git a/examples/common/pigweed/rpc_services/Attributes.h b/examples/common/pigweed/rpc_services/Attributes.h
index 223ec33..78e310f 100644
--- a/examples/common/pigweed/rpc_services/Attributes.h
+++ b/examples/common/pigweed/rpc_services/Attributes.h
@@ -18,12 +18,14 @@
 
 #pragma once
 
-#include "app/util/attribute-storage.h"
 #include "attributes_service/attributes_service.rpc.pb.h"
 #include "pigweed/rpc_services/internal/StatusUtils.h"
+
 #include <app-common/zap-generated/attribute-type.h>
 #include <app/InteractionModelEngine.h>
 #include <app/MessageDef/AttributeReportIBs.h>
+#include <app/util/attribute-storage.h>
+#include <app/util/ember-compatibility-functions.h>
 #include <lib/core/TLV.h>
 #include <lib/core/TLVTags.h>
 #include <lib/core/TLVTypes.h>
diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn
index 2ac0414..2641356 100644
--- a/src/app/BUILD.gn
+++ b/src/app/BUILD.gn
@@ -189,6 +189,13 @@
     "reporting/ReportSchedulerImpl.h",
     "reporting/SynchronizedReportSchedulerImpl.cpp",
     "reporting/SynchronizedReportSchedulerImpl.h",
+
+    # TODO: reporting header is part of interaction-model, however actual implementation depends
+    #       on generated code as subscriptions depend on attribute data versioning to determine
+    #       when "data changed" reports should be sent.
+    #
+    #       This breaks having `.h` and `.cpp` based off the same compilation unit and
+    #       should ideally be cleaned up.
     "reporting/reporting.h",
   ]
 
diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp
index 68ab452..74c7aed 100644
--- a/src/app/InteractionModelEngine.cpp
+++ b/src/app/InteractionModelEngine.cpp
@@ -32,6 +32,7 @@
 #include <app/AppConfig.h>
 #include <app/RequiredPrivilege.h>
 #include <app/util/af-types.h>
+#include <app/util/ember-compatibility-functions.h>
 #include <app/util/endpoint-config-api.h>
 #include <lib/core/Global.h>
 #include <lib/core/TLVUtilities.h>
diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h
index 22ec1fb..0e021a0 100644
--- a/src/app/InteractionModelEngine.h
+++ b/src/app/InteractionModelEngine.h
@@ -679,75 +679,11 @@
                                   CommandHandler * apCommandObj);
 
 /**
- *  Check whether the given cluster exists on the given endpoint and supports
- *  the given command.  If it does, Success will be returned.  If it does not,
- *  one of UnsupportedEndpoint, UnsupportedCluster, or UnsupportedCommand
- *  will be returned, depending on how the command fails to exist.
- */
-Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath);
-
-/**
- *  Fetch attribute value and version info and write to the AttributeReport provided.
- *  The ReadSingleClusterData will do everything required for encoding an attribute, i.e. it will try to put one or more
- * AttributeReportIB to the AttributeReportIBs::Builder.
- *  When the endpoint / cluster / attribute data specified by aPath does not exist, corresponding interaction
- * model error code will be put into aAttributeReports, and CHIP_NO_ERROR will be returned. If the data exists on the server, the
- * data (with tag kData) and the data version (with tag kDataVersion) will be put into aAttributeReports. TLVWriter error will be
- * returned if any error occurred while encoding these values. This function is implemented by CHIP as a part of cluster data
- * storage & management.
- *
- *  @param[in]    aSubjectDescriptor    The subject descriptor for the read.
- *  @param[in]    aPath                 The concrete path of the data being read.
- *  @param[in]    aAttributeReports      The TLV Builder for Cluter attribute builder.
- *
- *  @retval  CHIP_NO_ERROR on success
- */
-CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered,
-                                 const ConcreteReadAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports,
-                                 AttributeValueEncoder::AttributeEncodeState * apEncoderState);
-
-/**
- *  Check whether concrete attribute path is an "existent attribute path" in spec terms.
- *  @param[in]    aPath                 The concrete path of the data being read.
- *  @retval  boolean   true if the concrete attribute path indicates an attribute that exists on the node.
- */
-bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath);
-
-/**
  *  Get the registered attribute access override. nullptr when attribute access override is not found.
  *
  * TODO(#16806): This function and registerAttributeAccessOverride can be member functions of InteractionModelEngine.
  */
 AttributeAccessInterface * GetAttributeAccessOverride(EndpointId aEndpointId, ClusterId aClusterId);
 
-/**
- * TODO: Document.
- */
-CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor,
-                                  const ConcreteDataAttributePath & aAttributePath, TLV::TLVReader & aReader,
-                                  WriteHandler * apWriteHandler);
-
-/**
- * Check if the given cluster has the given DataVersion.
- */
-bool IsClusterDataVersionEqual(const ConcreteClusterPath & aConcreteClusterPath, DataVersion aRequiredVersion);
-
-/**
- * Returns true if device type is on endpoint, false otherwise.
- */
-bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint);
-
-/**
- * Returns the metadata of the attribute for the given path.
- *
- * @retval The metadata of the attribute, will return null if the given attribute does not exists.
- */
-const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aPath);
-
-/**
- * Returns the event support status for the given event, as an interaction model status.
- */
-Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventPath & aPath);
-
 } // namespace app
 } // namespace chip
diff --git a/src/app/WriteHandler.cpp b/src/app/WriteHandler.cpp
index c0bc52b..f7fc1f3 100644
--- a/src/app/WriteHandler.cpp
+++ b/src/app/WriteHandler.cpp
@@ -24,6 +24,7 @@
 #include <app/WriteHandler.h>
 #include <app/reporting/Engine.h>
 #include <app/util/MatterCallbacks.h>
+#include <app/util/ember-compatibility-functions.h>
 #include <credentials/GroupDataProvider.h>
 #include <lib/support/TypeTraits.h>
 
diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake
index 6e84ce2..5573eeb 100644
--- a/src/app/chip_data_model.cmake
+++ b/src/app/chip_data_model.cmake
@@ -135,6 +135,7 @@
     target_sources(${APP_TARGET} ${SCOPE}
         ${CHIP_APP_BASE_DIR}/../../zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp
         ${CHIP_APP_BASE_DIR}/../../zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
+        ${CHIP_APP_BASE_DIR}/reporting/reporting.cpp
         ${CHIP_APP_BASE_DIR}/util/attribute-storage.cpp
         ${CHIP_APP_BASE_DIR}/util/attribute-table.cpp
         ${CHIP_APP_BASE_DIR}/util/binding-table.cpp
diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni
index eb8036b..c8a30b1 100644
--- a/src/app/chip_data_model.gni
+++ b/src/app/chip_data_model.gni
@@ -204,6 +204,7 @@
 
     if (!chip_build_controller_dynamic_server) {
       sources += [
+        "${_app_root}/reporting/reporting.cpp",
         "${_app_root}/util/DataModelHandler.cpp",
         "${_app_root}/util/attribute-storage.cpp",
         "${_app_root}/util/attribute-table.cpp",
diff --git a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
index ddaed23..cae604c 100644
--- a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
+++ b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
@@ -22,6 +22,7 @@
 #include <app/clusters/mode-base-server/mode-base-server.h>
 #include <app/reporting/reporting.h>
 #include <app/util/attribute-storage.h>
+#include <app/util/ember-compatibility-functions.h>
 
 using namespace chip;
 using namespace chip::app;
diff --git a/src/app/clusters/pump-configuration-and-control-server/pump-configuration-and-control-server.cpp b/src/app/clusters/pump-configuration-and-control-server/pump-configuration-and-control-server.cpp
index c3eebe2..eea313c 100644
--- a/src/app/clusters/pump-configuration-and-control-server/pump-configuration-and-control-server.cpp
+++ b/src/app/clusters/pump-configuration-and-control-server/pump-configuration-and-control-server.cpp
@@ -26,6 +26,7 @@
 #include <app/InteractionModelEngine.h>
 #include <app/util/attribute-storage.h>
 #include <app/util/config.h>
+#include <app/util/ember-compatibility-functions.h>
 
 using namespace chip;
 using namespace chip::app;
diff --git a/src/app/dynamic_server/AccessControl.cpp b/src/app/dynamic_server/AccessControl.cpp
index 38928b5..d091b9a 100644
--- a/src/app/dynamic_server/AccessControl.cpp
+++ b/src/app/dynamic_server/AccessControl.cpp
@@ -25,6 +25,11 @@
 #include <lib/core/CHIPError.h>
 #include <lib/core/Global.h>
 
+// TODO: this include is unclear as dynamic server should NOT link those.
+//       we should probably have some separate includes here for dynamic
+//       server
+#include <app/util/ember-compatibility-functions.h>
+
 using namespace chip;
 using namespace chip::Access;
 using namespace chip::app::Clusters;
diff --git a/src/app/dynamic_server/DynamicDispatcher.cpp b/src/app/dynamic_server/DynamicDispatcher.cpp
index ca396c1..c54e7d8 100644
--- a/src/app/dynamic_server/DynamicDispatcher.cpp
+++ b/src/app/dynamic_server/DynamicDispatcher.cpp
@@ -15,6 +15,7 @@
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
+#include <app/util/ember-compatibility-functions.h>
 
 #include <access/SubjectDescriptor.h>
 #include <app-common/zap-generated/callback.h>
diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp
index 2dd730c..e210808 100644
--- a/src/app/reporting/Engine.cpp
+++ b/src/app/reporting/Engine.cpp
@@ -32,6 +32,7 @@
 #include <app/RequiredPrivilege.h>
 #include <app/reporting/Engine.h>
 #include <app/util/MatterCallbacks.h>
+#include <app/util/ember-compatibility-functions.h>
 
 using namespace chip::Access;
 
diff --git a/src/app/reporting/reporting.cpp b/src/app/reporting/reporting.cpp
new file mode 100644
index 0000000..8ed06a8
--- /dev/null
+++ b/src/app/reporting/reporting.cpp
@@ -0,0 +1,79 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#include "reporting.h"
+
+#include <app/AttributePathParams.h>
+#include <app/InteractionModelEngine.h>
+#include <app/util/af.h>
+#include <platform/LockTracker.h>
+
+using namespace chip;
+using namespace chip::app;
+
+namespace {
+
+void IncreaseClusterDataVersion(const ConcreteClusterPath & aConcreteClusterPath)
+{
+    DataVersion * version = emberAfDataVersionStorage(aConcreteClusterPath);
+    if (version == nullptr)
+    {
+        ChipLogError(DataManagement, "Endpoint %x, Cluster " ChipLogFormatMEI " not found in IncreaseClusterDataVersion!",
+                     aConcreteClusterPath.mEndpointId, ChipLogValueMEI(aConcreteClusterPath.mClusterId));
+    }
+    else
+    {
+        (*(version))++;
+        ChipLogDetail(DataManagement, "Endpoint %x, Cluster " ChipLogFormatMEI " update version to %" PRIx32,
+                      aConcreteClusterPath.mEndpointId, ChipLogValueMEI(aConcreteClusterPath.mClusterId), *(version));
+    }
+}
+
+} // namespace
+
+void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
+{
+    // Attribute writes have asserted this already, but this assert should catch
+    // applications notifying about changes from their end.
+    assertChipStackLockedByCurrentThread();
+
+    AttributePathParams info;
+    info.mClusterId   = clusterId;
+    info.mAttributeId = attributeId;
+    info.mEndpointId  = endpoint;
+
+    IncreaseClusterDataVersion(ConcreteClusterPath(endpoint, clusterId));
+    InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info);
+}
+
+void MatterReportingAttributeChangeCallback(const ConcreteAttributePath & aPath)
+{
+    return MatterReportingAttributeChangeCallback(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId);
+}
+
+void MatterReportingAttributeChangeCallback(EndpointId endpoint)
+{
+    // Attribute writes have asserted this already, but this assert should catch
+    // applications notifying about changes from their end.
+    assertChipStackLockedByCurrentThread();
+
+    AttributePathParams info;
+    info.mEndpointId = endpoint;
+
+    // We are adding or enabling a whole endpoint, in this case, we do not touch the cluster data version.
+
+    InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info);
+}
diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp
index e046080..3d7ceb5 100644
--- a/src/app/server/Server.cpp
+++ b/src/app/server/Server.cpp
@@ -24,6 +24,7 @@
 #include <app/server/Dnssd.h>
 #include <app/server/EchoHandler.h>
 #include <app/util/DataModelHandler.h>
+#include <app/util/ember-compatibility-functions.h>
 
 #if CONFIG_NETWORK_LAYER_BLE
 #include <ble/BLEEndPoint.h>
diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp
index f8c8cca..81bf518 100644
--- a/src/app/util/ember-compatibility-functions.cpp
+++ b/src/app/util/ember-compatibility-functions.cpp
@@ -14,12 +14,7 @@
  *    See the License for the specific language governing permissions and
  *    limitations under the License.
  */
-
-/**
- *    @file
- *          Contains the functions for compatibility with ember ZCL inner state
- *          when calling ember callbacks.
- */
+#include <app/util/ember-compatibility-functions.h>
 
 #include <access/AccessControl.h>
 #include <app/CommandHandlerInterface.h>
@@ -272,22 +267,6 @@
     return CHIP_NO_ERROR;
 }
 
-void IncreaseClusterDataVersion(const ConcreteClusterPath & aConcreteClusterPath)
-{
-    DataVersion * version = emberAfDataVersionStorage(aConcreteClusterPath);
-    if (version == nullptr)
-    {
-        ChipLogError(DataManagement, "Endpoint %x, Cluster " ChipLogFormatMEI " not found in IncreaseClusterDataVersion!",
-                     aConcreteClusterPath.mEndpointId, ChipLogValueMEI(aConcreteClusterPath.mClusterId));
-    }
-    else
-    {
-        (*(version))++;
-        ChipLogDetail(DataManagement, "Endpoint %x, Cluster " ChipLogFormatMEI " update version to %" PRIx32,
-                      aConcreteClusterPath.mEndpointId, ChipLogValueMEI(aConcreteClusterPath.mClusterId), *(version));
-    }
-}
-
 CHIP_ERROR SendSuccessStatus(AttributeReportIB::Builder & aAttributeReport, AttributeDataIB::Builder & aAttributeDataIBBuilder)
 {
     ReturnErrorOnFailure(aAttributeDataIBBuilder.EndOfAttributeDataIB());
@@ -1123,37 +1102,3 @@
 
 } // namespace app
 } // namespace chip
-
-void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
-{
-    // Attribute writes have asserted this already, but this assert should catch
-    // applications notifying about changes from their end.
-    assertChipStackLockedByCurrentThread();
-
-    AttributePathParams info;
-    info.mClusterId   = clusterId;
-    info.mAttributeId = attributeId;
-    info.mEndpointId  = endpoint;
-
-    IncreaseClusterDataVersion(ConcreteClusterPath(endpoint, clusterId));
-    InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info);
-}
-
-void MatterReportingAttributeChangeCallback(const ConcreteAttributePath & aPath)
-{
-    return MatterReportingAttributeChangeCallback(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId);
-}
-
-void MatterReportingAttributeChangeCallback(EndpointId endpoint)
-{
-    // Attribute writes have asserted this already, but this assert should catch
-    // applications notifying about changes from their end.
-    assertChipStackLockedByCurrentThread();
-
-    AttributePathParams info;
-    info.mEndpointId = endpoint;
-
-    // We are adding or enabling a whole endpoint, in this case, we do not touch the cluster data version.
-
-    InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info);
-}
diff --git a/src/app/util/ember-compatibility-functions.h b/src/app/util/ember-compatibility-functions.h
new file mode 100644
index 0000000..a0888ac
--- /dev/null
+++ b/src/app/util/ember-compatibility-functions.h
@@ -0,0 +1,94 @@
+/*
+ *    Copyright (c) 2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#pragma once
+
+#include <access/SubjectDescriptor.h>
+#include <app/AttributeAccessInterface.h>
+#include <app/ConcreteAttributePath.h>
+#include <app/ConcreteCommandPath.h>
+#include <app/ConcreteEventPath.h>
+#include <app/WriteHandler.h>
+#include <app/util/attribute-metadata.h>
+#include <protocols/interaction_model/StatusCode.h>
+
+namespace chip {
+namespace app {
+
+/**
+ *  Check whether the given cluster exists on the given endpoint and supports
+ *  the given command.  If it does, Success will be returned.  If it does not,
+ *  one of UnsupportedEndpoint, UnsupportedCluster, or UnsupportedCommand
+ *  will be returned, depending on how the command fails to exist.
+ */
+Protocols::InteractionModel::Status ServerClusterCommandExists(const ConcreteCommandPath & aCommandPath);
+
+/**
+ *  Check whether concrete attribute path is an "existent attribute path" in spec terms.
+ *  @param[in]    aPath                 The concrete path of the data being read.
+ *  @retval  boolean   true if the concrete attribute path indicates an attribute that exists on the node.
+ */
+bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath);
+
+/**
+ *  Fetch attribute value and version info and write to the AttributeReport provided.
+ *  The ReadSingleClusterData will do everything required for encoding an attribute, i.e. it will try to put one or more
+ * AttributeReportIB to the AttributeReportIBs::Builder.
+ *  When the endpoint / cluster / attribute data specified by aPath does not exist, corresponding interaction
+ * model error code will be put into aAttributeReports, and CHIP_NO_ERROR will be returned. If the data exists on the server, the
+ * data (with tag kData) and the data version (with tag kDataVersion) will be put into aAttributeReports. TLVWriter error will be
+ * returned if any error occurred while encoding these values. This function is implemented by CHIP as a part of cluster data
+ * storage & management.
+ *
+ *  @param[in]    aSubjectDescriptor    The subject descriptor for the read.
+ *  @param[in]    aPath                 The concrete path of the data being read.
+ *  @param[in]    aAttributeReports      The TLV Builder for Cluter attribute builder.
+ *
+ *  @retval  CHIP_NO_ERROR on success
+ */
+CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered,
+                                 const ConcreteReadAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports,
+                                 AttributeValueEncoder::AttributeEncodeState * apEncoderState);
+
+/**
+ * Returns the metadata of the attribute for the given path.
+ *
+ * @retval The metadata of the attribute, will return null if the given attribute does not exists.
+ */
+const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aPath);
+
+/**
+ * TODO: Document.
+ */
+CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, const ConcreteDataAttributePath & aPath,
+                                  TLV::TLVReader & aReader, WriteHandler * apWriteHandler);
+
+/**
+ * Check if the given cluster has the given DataVersion.
+ */
+bool IsClusterDataVersionEqual(const ConcreteClusterPath & aConcreteClusterPath, DataVersion aRequiredVersion);
+
+/**
+ * Returns true if device type is on endpoint, false otherwise.
+ */
+bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint);
+
+/**
+ * Returns the event support status for the given event, as an interaction model status.
+ */
+Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventPath & aPath);
+
+} // namespace app
+} // namespace chip
diff --git a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAccessControl.mm b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAccessControl.mm
index abf386b..28dacef 100644
--- a/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAccessControl.mm
+++ b/src/darwin/Framework/CHIP/ServerEndpoint/MTRServerAccessControl.mm
@@ -32,6 +32,7 @@
 #include <lib/core/Global.h>
 #include <lib/core/NodeId.h>
 
+#include <app/util/ember-compatibility-functions.h>
 #include <app/util/privilege-storage.h>
 
 using namespace chip;
diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
index c6111d8..74ab025 100644
--- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
+++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
@@ -262,6 +262,8 @@
 		7596A8512878709F004DAE0E /* MTRAsyncCallbackQueueTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7596A8502878709F004DAE0E /* MTRAsyncCallbackQueueTests.m */; };
 		7596A85528788557004DAE0E /* MTRClusters.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7596A85228788557004DAE0E /* MTRClusters.mm */; };
 		7596A85728788557004DAE0E /* MTRClusters.h in Headers */ = {isa = PBXBuildFile; fileRef = 7596A85428788557004DAE0E /* MTRClusters.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		75A202E52BA8DBAC00A771DD /* reporting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 75A202E42BA8DBAC00A771DD /* reporting.cpp */; };
+		75A202E62BA8DBAC00A771DD /* reporting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 75A202E42BA8DBAC00A771DD /* reporting.cpp */; };
 		75B0D01E2B71B47F002074DD /* MTRDeviceTestDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 75B0D01D2B71B47F002074DD /* MTRDeviceTestDelegate.m */; };
 		75B765C12A1D71BC0014719B /* MTRAttributeSpecifiedCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 75B765C02A1D71BC0014719B /* MTRAttributeSpecifiedCheck.h */; };
 		75B765C32A1D82D30014719B /* MTRAttributeSpecifiedCheck.mm in Sources */ = {isa = PBXBuildFile; fileRef = 75B765C22A1D82D30014719B /* MTRAttributeSpecifiedCheck.mm */; };
@@ -669,6 +671,7 @@
 		7596A8502878709F004DAE0E /* MTRAsyncCallbackQueueTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRAsyncCallbackQueueTests.m; sourceTree = "<group>"; };
 		7596A85228788557004DAE0E /* MTRClusters.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRClusters.mm; sourceTree = "<group>"; };
 		7596A85428788557004DAE0E /* MTRClusters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRClusters.h; sourceTree = "<group>"; };
+		75A202E42BA8DBAC00A771DD /* reporting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reporting.cpp; sourceTree = "<group>"; };
 		75B0D01C2B71B46F002074DD /* MTRDeviceTestDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceTestDelegate.h; sourceTree = "<group>"; };
 		75B0D01D2B71B47F002074DD /* MTRDeviceTestDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRDeviceTestDelegate.m; sourceTree = "<group>"; };
 		75B765BF2A1D70F80014719B /* MTRAttributeSpecifiedCheck-src.zapt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "MTRAttributeSpecifiedCheck-src.zapt"; sourceTree = "<group>"; };
@@ -1013,6 +1016,7 @@
 		1E857311265519DE0050A4D9 /* app */ = {
 			isa = PBXGroup;
 			children = (
+				75A202E72BA8DBB700A771DD /* reporting */,
 				5143041F2914CED9004DC7FE /* generic-callback-stubs.cpp */,
 				514C79F22B62ED5500DD6D7B /* attribute-storage.cpp */,
 				514C79EF2B62ADDA00DD6D7B /* descriptor.cpp */,
@@ -1166,6 +1170,14 @@
 			path = ServerEndpoint;
 			sourceTree = "<group>";
 		};
+		75A202E72BA8DBB700A771DD /* reporting */ = {
+			isa = PBXGroup;
+			children = (
+				75A202E42BA8DBAC00A771DD /* reporting.cpp */,
+			);
+			path = reporting;
+			sourceTree = "<group>";
+		};
 		B20252832459E34F00F97062 = {
 			isa = PBXGroup;
 			children = (
@@ -1788,6 +1800,7 @@
 				B45373F32A9FEC1A00807602 /* server-ws.c in Sources */,
 				03F430AA2994113500166449 /* sysunix.c in Sources */,
 				B45373C42A9FEA9100807602 /* dummy-callback.c in Sources */,
+				75A202E62BA8DBAC00A771DD /* reporting.cpp in Sources */,
 				514C79EE2B62ADCD00DD6D7B /* ember-compatibility-functions.cpp in Sources */,
 				039145E82993179300257B3E /* GetCommissionerNodeIdCommand.mm in Sources */,
 				0395469F2991DFC5006D42A8 /* json_reader.cpp in Sources */,
@@ -1896,6 +1909,7 @@
 				51B22C262740CB32008D5055 /* MTRStructsObjc.mm in Sources */,
 				2C222AD1255C620600E446B9 /* MTRBaseDevice.mm in Sources */,
 				1EC3238D271999E2002A8BF0 /* cluster-objects.cpp in Sources */,
+				75A202E52BA8DBAC00A771DD /* reporting.cpp in Sources */,
 				3CF134A9289D8D800017A19E /* MTRCSRInfo.mm in Sources */,
 				991DC0892475F47D00C13860 /* MTRDeviceController.mm in Sources */,
 				B2E0D7B7245B0B5C003C5B48 /* MTRQRCodeSetupPayloadParser.mm in Sources */,