diff --git a/subprojects/callback-manager/src/callback_manager.cpp b/subprojects/callback-manager/src/callback_manager.cpp
new file mode 100644
index 0000000..4d54ffe
--- /dev/null
+++ b/subprojects/callback-manager/src/callback_manager.cpp
@@ -0,0 +1,384 @@
+/*
+// Copyright (c) 2019 Intel Corporation
+//
+// 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 "callback_manager.hpp"
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_map.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <variant>
+
+constexpr const char* fatalLedPath =
+    "/xyz/openbmc_project/led/groups/status_critical";
+constexpr const char* criticalLedPath =
+    "/xyz/openbmc_project/led/groups/status_non_critical";
+constexpr const char* warningLedPath =
+    "/xyz/openbmc_project/led/groups/status_degraded";
+constexpr const char* okLedPath = "/xyz/openbmc_project/led/groups/status_ok";
+
+constexpr const char* ledIface = "xyz.openbmc_project.Led.Group";
+constexpr const char* ledAssertProp = "Asserted";
+constexpr const char* ledManagerBusname =
+    "xyz.openbmc_project.LED.GroupManager";
+
+std::unique_ptr<AssociationManager> associationManager;
+
+enum class StatusSetting
+{
+    none,
+    ok,
+    warn,
+    critical,
+    fatal
+};
+
+constexpr const bool debug = false;
+
+// final led state tracking
+StatusSetting currentPriority = StatusSetting::none;
+
+// maps of <object-path, <property, asserted>>
+boost::container::flat_map<std::string,
+                           boost::container::flat_map<std::string, bool>>
+    fatalAssertMap;
+boost::container::flat_map<std::string,
+                           boost::container::flat_map<std::string, bool>>
+    criticalAssertMap;
+boost::container::flat_map<std::string,
+                           boost::container::flat_map<std::string, bool>>
+    warningAssertMap;
+
+std::vector<std::string> assertedInMap(
+    const boost::container::flat_map<
+        std::string, boost::container::flat_map<std::string, bool>>& map)
+{
+    std::vector<std::string> ret;
+    // if any of the properties are true, return true
+    for (const auto& pair : map)
+    {
+        for (const auto& item : pair.second)
+        {
+            if (item.second)
+            {
+                ret.push_back(pair.first);
+            }
+        }
+    }
+    return ret;
+}
+
+void updateLedStatus(std::shared_ptr<sdbusplus::asio::connection>& conn,
+                     bool forceRefresh = false)
+{
+    std::vector<std::string> fatalVector = assertedInMap(fatalAssertMap);
+    bool fatal = fatalVector.size();
+
+    std::vector<std::string> criticalVector = assertedInMap(criticalAssertMap);
+    bool critical = criticalVector.size();
+
+    std::vector<std::string> warningVector = assertedInMap(warningAssertMap);
+    bool warn = warningVector.size();
+
+    associationManager->setLocalAssociations(fatalVector, criticalVector,
+                                             warningVector);
+
+    StatusSetting last = currentPriority;
+    std::vector<std::pair<std::string, std::variant<bool>>> ledsToSet;
+    if (forceRefresh)
+    {
+        ledsToSet.push_back(std::make_pair(fatalLedPath, false));
+        ledsToSet.push_back(std::make_pair(criticalLedPath, false));
+        ledsToSet.push_back(std::make_pair(warningLedPath, false));
+        ledsToSet.push_back(std::make_pair(okLedPath, false));
+        for (const auto& ledPair : ledsToSet)
+        {
+            conn->async_method_call(
+                [ledPair](const boost::system::error_code ec) {
+                    std::ios_base::fmtflags originalFlags = std::cerr.flags();
+                    if (ec)
+                    {
+                        std::cerr << "Cannot set " << ledPair.first << " to "
+                                  << std::boolalpha
+                                  << std::get<bool>(ledPair.second) << "\n";
+                        std::cerr.flags(originalFlags);
+                    }
+                    if constexpr (debug)
+                    {
+                        std::cerr << "Set " << ledPair.first << " to "
+                                  << std::boolalpha
+                                  << std::get<bool>(ledPair.second) << "\n";
+                        std::cerr.flags(originalFlags);
+                    }
+                },
+                ledManagerBusname, ledPair.first,
+                "org.freedesktop.DBus.Properties", "Set", ledIface,
+                ledAssertProp, ledPair.second);
+        }
+    }
+    if (fatal)
+    {
+        currentPriority = StatusSetting::fatal;
+    }
+    else if (critical)
+    {
+        currentPriority = StatusSetting::critical;
+    }
+    else if (warn)
+    {
+        currentPriority = StatusSetting::warn;
+    }
+    else
+    {
+        currentPriority = StatusSetting::ok;
+    }
+
+    if (last != currentPriority || forceRefresh)
+    {
+        switch (currentPriority)
+        {
+            case (StatusSetting::fatal):
+            {
+                ledsToSet.push_back(std::make_pair(fatalLedPath, true));
+                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
+                ledsToSet.push_back(std::make_pair(warningLedPath, false));
+                ledsToSet.push_back(std::make_pair(okLedPath, false));
+                break;
+            }
+            case (StatusSetting::critical):
+            {
+                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
+                ledsToSet.push_back(std::make_pair(criticalLedPath, true));
+                ledsToSet.push_back(std::make_pair(warningLedPath, false));
+                ledsToSet.push_back(std::make_pair(okLedPath, false));
+                break;
+            }
+            case (StatusSetting::warn):
+            {
+                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
+                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
+                ledsToSet.push_back(std::make_pair(warningLedPath, true));
+                ledsToSet.push_back(std::make_pair(okLedPath, false));
+                break;
+            }
+            case (StatusSetting::ok):
+            {
+                ledsToSet.push_back(std::make_pair(fatalLedPath, false));
+                ledsToSet.push_back(std::make_pair(criticalLedPath, false));
+                ledsToSet.push_back(std::make_pair(warningLedPath, false));
+                ledsToSet.push_back(std::make_pair(okLedPath, true));
+                break;
+            }
+            case (StatusSetting::none):
+            default:
+                break;
+        }
+    }
+
+    for (const auto& ledPair : ledsToSet)
+    {
+        conn->async_method_call(
+            [ledPair](const boost::system::error_code ec) {
+                if (ec)
+                {
+                    std::cerr << "Cannot set " << ledPair.first << " to "
+                              << std::boolalpha
+                              << std::get<bool>(ledPair.second) << "\n";
+                }
+                if constexpr (debug)
+                {
+                    std::cerr
+                        << "Set " << ledPair.first << " to " << std::boolalpha
+                        << std::get<bool>(ledPair.second) << "\n";
+                }
+            },
+            ledManagerBusname, ledPair.first, "org.freedesktop.DBus.Properties",
+            "Set", ledIface, ledAssertProp, ledPair.second);
+    }
+}
+
+void createThresholdMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+    static sdbusplus::bus::match_t match(
+        static_cast<sdbusplus::bus_t&>(*conn),
+        "type='signal',member='ThresholdAsserted'",
+        [&conn](sdbusplus::message_t& message) {
+            std::string sensorName;
+            std::string thresholdInterface;
+            std::string event;
+            bool assert;
+            double assertValue;
+
+            try
+            {
+                message.read(sensorName, thresholdInterface, event, assert,
+                             assertValue);
+            }
+            catch (sdbusplus::exception_t&)
+            {
+                return;
+            }
+            if constexpr (debug)
+            {
+                std::cerr << "Threshold callback: SensorName = " << sensorName
+                          << ", Event = " << event << ", Asserted = " << assert
+                          << "\n";
+            }
+
+            if (event == "CriticalAlarmLow")
+            {
+                criticalAssertMap[message.get_path()]["low"] = assert;
+            }
+            else if (event == "CriticalAlarmHigh")
+            {
+                criticalAssertMap[message.get_path()]["high"] = assert;
+            }
+            else if (event == "WarningAlarmLow")
+            {
+                warningAssertMap[message.get_path()]["low"] = assert;
+            }
+            else if (event == "WarningAlarmHigh")
+            {
+                warningAssertMap[message.get_path()]["high"] = assert;
+            }
+
+            associationManager->setSensorAssociations(
+                assertedInMap(criticalAssertMap),
+                assertedInMap(warningAssertMap));
+
+            updateLedStatus(conn);
+        });
+}
+
+void createAssociationMatch(std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+    static sdbusplus::bus::match_t match(
+        static_cast<sdbusplus::bus_t&>(*conn),
+        "type='signal',interface='org.freedesktop.DBus.Properties',"
+        "arg0namespace='" +
+            std::string(associationIface) + "'",
+        [&conn](sdbusplus::message_t& message) {
+            if (message.get_path() == rootPath)
+            {
+                return; // it's us
+            }
+            std::string objectName;
+            boost::container::flat_map<std::string,
+                                       std::variant<std::vector<Association>>>
+                values;
+            try
+            {
+                message.read(objectName, values);
+            }
+            catch (sdbusplus::exception_t&)
+            {
+                return;
+            }
+
+            if constexpr (debug)
+            {
+                std::cerr << "Association callback " << message.get_path()
+                          << "\n";
+            }
+
+            auto findAssociations = values.find("Associations");
+            if (findAssociations == values.end())
+            {
+                return;
+            }
+            const std::vector<Association>* associations =
+                std::get_if<std::vector<Association>>(
+                    &findAssociations->second);
+
+            if (associations == nullptr)
+            {
+                std::cerr << "Illegal Association on " << message.get_path()
+                          << "\n";
+                return;
+            }
+
+            bool localWarning = false;
+            bool localCritical = false;
+            bool globalWarning = false;
+            bool globalCritical = false;
+
+            for (const auto& [forward, reverse, path] : *associations)
+            {
+                if (path == rootPath)
+                {
+                    globalWarning = globalWarning ? true : reverse == "warning";
+                    globalCritical =
+                        globalCritical ? true : reverse == "critical";
+
+                    if constexpr (1)
+                    {
+                        std::cerr << "got global ";
+                    }
+                }
+                else
+                {
+                    localWarning = localWarning ? true : reverse == "warning";
+                    localCritical =
+                        localCritical ? true : reverse == "critical";
+                }
+                if (globalCritical && localCritical)
+                {
+                    break;
+                }
+            }
+
+            bool fatal = globalCritical && localCritical;
+            bool critical = globalWarning && localCritical;
+            bool warning = globalWarning && !critical;
+
+            fatalAssertMap[message.get_path()]["association"] = fatal;
+            criticalAssertMap[message.get_path()]["association"] = critical;
+            warningAssertMap[message.get_path()]["association"] = warning;
+
+            updateLedStatus(conn);
+        });
+}
+
+int main(int /*argc*/, char** /*argv*/)
+{
+    boost::asio::io_context io;
+    auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+    conn->request_name("xyz.openbmc_project.CallbackManager");
+    sdbusplus::asio::object_server objServer(conn);
+    std::shared_ptr<sdbusplus::asio::dbus_interface> rootIface =
+        objServer.add_interface(rootPath,
+                                "xyz.openbmc_project.CallbackManager");
+    rootIface->register_method("RetriggerLEDUpdate", [&conn]() {
+        updateLedStatus(conn, true);
+    });
+    rootIface->initialize();
+
+    std::shared_ptr<sdbusplus::asio::dbus_interface> inventoryIface =
+        objServer.add_interface(rootPath, globalInventoryIface);
+    inventoryIface->initialize();
+
+    associationManager = std::make_unique<AssociationManager>(objServer, conn);
+
+    createThresholdMatch(conn);
+    createAssociationMatch(conn);
+    updateLedStatus(conn);
+
+    io.run();
+
+    return 0;
+}
