diff --git a/include/crm/cib.h b/include/crm/cib.h
index 1d52de5d75..fe04d91375 100644
--- a/include/crm/cib.h
+++ b/include/crm/cib.h
@@ -1,61 +1,66 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CIB__H
 #  define PCMK__CRM_CIB__H
 
 #  include <glib.h>             // gboolean
 #  include <crm/common/ipc.h>
 #  include <crm/common/xml.h>
 #  include <crm/cib/cib_types.h>
 #  include <crm/cib/util.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Cluster Configuration
  * \ingroup cib
  */
 
 // Use compare_version() for doing comparisons
 #  define CIB_FEATURE_SET "2.0"
 
 /* Core functions */
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 cib_t *cib_new(void);
+
 cib_t *cib_native_new(void);
 cib_t *cib_file_new(const char *filename);
 cib_t *cib_remote_new(const char *server, const char *user, const char *passwd, int port,
                       gboolean encrypted);
 
 cib_t *cib_new_no_shadow(void);
 char *get_shadow_file(const char *name);
 cib_t *cib_shadow_new(const char *name);
 
 void cib_free_notify(cib_t *cib);
 void cib_free_callbacks(cib_t *cib);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 void cib_delete(cib_t * cib);
 
 void cib_dump_pending_callbacks(void);
 int num_cib_op_callbacks(void);
 void remove_cib_op_callback(int call_id, gboolean all_callbacks);
 
 #  define CIB_LIBRARY "libcib.so.27"
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/cib_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/cib/cib_types.h b/include/crm/cib/cib_types.h
index ab2652922c..281c16ec70 100644
--- a/include/crm/cib/cib_types.h
+++ b/include/crm/cib/cib_types.h
@@ -1,386 +1,410 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CIB_CIB_TYPES__H
 #  define PCMK__CRM_CIB_CIB_TYPES__H
 
 #  include <glib.h>             // gboolean, GList
 #  include <libxml/tree.h>      // xmlNode
 #  include <crm/common/ipc.h>
 #  include <crm/common/xml.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Data types for Cluster Information Base access
  * \ingroup cib
  */
 
 enum cib_variant {
     cib_undefined = 0,
     cib_native    = 1,
     cib_file      = 2,
     cib_remote    = 3,
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     //! \deprecated This value will be removed in a future release
     cib_database  = 4,
 #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 };
 
 enum cib_state {
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     cib_connected_command,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     cib_connected_query,
+
     cib_disconnected
 };
 
 enum cib_conn_type {
     cib_command,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     cib_query,
+
     cib_no_connection,
     cib_command_nonblocking,
 };
 
 enum cib_call_options {
     cib_none            = 0,
     cib_verbose         = (1 << 0),  //!< Prefer stderr to logs
     cib_xpath           = (1 << 1),
     cib_multiple        = (1 << 2),
     cib_can_create      = (1 << 3),
     cib_discard_reply   = (1 << 4),
     cib_no_children     = (1 << 5),
     cib_xpath_address   = (1 << 6),
 
     //! \deprecated This value will be removed in a future release
     cib_mixed_update    = (1 << 7),
 
     /* @COMPAT: cib_scope_local is processed only in the legacy function
      * parse_local_options_v1().
      *
      * If (host == NULL):
      * * In legacy mode, the CIB manager forwards a request to the primary
      *   instance unless cib_scope_local is set or the local node is primary.
      * * Outside of legacy mode:
      *   * If a request modifies the CIB, the CIB manager forwards it to all
      *     nodes.
      *   * Otherwise, the CIB manager processes the request locally.
      *
      * There is no current use case for this implementing this flag in
      * non-legacy mode.
      */
 
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     //! \deprecated This value will be removed in a future release
     cib_scope_local     = (1 << 8),
 
     cib_dryrun          = (1 << 9),
 
     /*!
      * \brief Process request when the client commits the active transaction
      *
      * Add the request to the client's active transaction instead of processing
      * it immediately. If the client has no active transaction, or if the
      * request is not supported in transactions, the call will fail.
      *
      * The request is added to the transaction synchronously, and the return
      * value indicates whether it was added successfully.
      *
      * Refer to \p cib_api_operations_t:init_transaction() and
      * \p cib_api_operations_t:end_transaction() for more details on CIB
      * transactions.
      */
     cib_transaction     = (1 << 10),
 
     /*!
      * \brief Treat new attribute values as atomic score updates where possible
      *
      * This option takes effect when updating XML attributes. For an attribute
      * named \c "name", if the new value is \c "name++" or \c "name+=X" for some
      * score \c X, the new value is set as follows:
      * * If attribute \c "name" is not already set to some value in the element
      *   being updated, the new value is set as a literal string.
      * * If the new value is \c "name++", then the attribute is set to its
      *   existing value (parsed as a score) plus 1.
      * * If the new value is \c "name+=X" for some score \c X, then the
      *   attribute is set to its existing value plus \c X, where the existing
      *   value and \c X are parsed and added as scores.
      *
      * Scores are integer values capped at \c INFINITY and \c -INFINITY. Refer
      * to Pacemaker Explained and to the \c char2score() function for more
      * details on scores, including how they're parsed and added.
      *
      * Note: This is implemented only for modify operations.
      */
     cib_score_update    = (1 << 11),
 
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     cib_sync_call       = (1 << 12),
+
     cib_no_mtime        = (1 << 13),
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     //! \deprecated This value will be removed in a future release
     cib_zero_copy       = (1 << 14),
 #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 
     cib_inhibit_notify  = (1 << 16),
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     //! \deprecated This value will be removed in a future release
     cib_quorum_override = (1 << 20),
 #endif // !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 
     //! \deprecated This value will be removed in a future release
     cib_inhibit_bcast   = (1 << 24),
 
     cib_force_diff      = (1 << 28),
 };
 
 typedef struct cib_s cib_t;
 
 typedef struct cib_api_operations_s {
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*signon) (cib_t *cib, const char *name, enum cib_conn_type type);
 
     //! \deprecated This method will be removed and should not be used
     int (*signon_raw) (cib_t *cib, const char *name, enum cib_conn_type type,
                        int *event_fd);
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*signoff) (cib_t *cib);
+
     int (*free) (cib_t *cib);
 
     //! \deprecated This method will be removed and should not be used
     int (*set_op_callback) (cib_t *cib, void (*callback) (const xmlNode *msg,
                                                           int callid, int rc,
                                                           xmlNode *output));
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*add_notify_callback) (cib_t *cib, const char *event,
                                 void (*callback) (const char *event,
                                                   xmlNode *msg));
+
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*del_notify_callback) (cib_t *cib, const char *event,
                                 void (*callback) (const char *event,
                                                   xmlNode *msg));
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*set_connection_dnotify) (cib_t *cib,
                                    void (*dnotify) (gpointer user_data));
 
     //! \deprecated This method will be removed and should not be used
     int (*inputfd) (cib_t *cib);
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated This method will be removed and should not be used
     int (*noop) (cib_t *cib, int call_options);
 
     int (*ping) (cib_t *cib, xmlNode **output_data, int call_options);
+
+    // NOTE: sbd (as of at least 1.5.2) uses this
     int (*query) (cib_t *cib, const char *section, xmlNode **output_data,
                   int call_options);
+
     int (*query_from) (cib_t *cib, const char *host, const char *section,
                        xmlNode **output_data, int call_options);
 
     //! \deprecated This method will be removed and should not be used
     int (*is_master) (cib_t *cib);
 
     //! \deprecated Use the set_primary() method instead
     int (*set_master) (cib_t *cib, int call_options);
 
     //! \deprecated Use the set_secondary() method instead
     int (*set_slave) (cib_t *cib, int call_options);
 
     //! \deprecated This method will be removed and should not be used
     int (*set_slave_all) (cib_t *cib, int call_options);
 
     int (*sync) (cib_t *cib, const char *section, int call_options);
     int (*sync_from) (cib_t *cib, const char *host, const char *section,
                       int call_options);
     int (*upgrade) (cib_t *cib, int call_options);
     int (*bump_epoch) (cib_t *cib, int call_options);
 
     /*!
      * The \c <failed> element in the reply to a failed creation call is
      * deprecated since 2.1.8.
      */
     int (*create) (cib_t *cib, const char *section, xmlNode *data,
                    int call_options);
     int (*modify) (cib_t *cib, const char *section, xmlNode *data,
                    int call_options);
 
     //! \deprecated Use the \p modify() method instead
     int (*update) (cib_t *cib, const char *section, xmlNode *data,
                    int call_options);
 
     int (*replace) (cib_t *cib, const char *section, xmlNode *data,
                     int call_options);
     int (*remove) (cib_t *cib, const char *section, xmlNode *data,
                    int call_options);
     int (*erase) (cib_t *cib, xmlNode **output_data, int call_options);
 
     //! \deprecated This method does nothing and should not be called
     int (*delete_absolute) (cib_t *cib, const char *section, xmlNode *data,
                             int call_options);
 
     //! \deprecated This method is not implemented and should not be used
     int (*quit) (cib_t *cib, int call_options);
 
     int (*register_notification) (cib_t *cib, const char *callback,
                                   int enabled);
     gboolean (*register_callback) (cib_t *cib, int call_id, int timeout,
                                    gboolean only_success, void *user_data,
                                    const char *callback_name,
                                    void (*callback) (xmlNode*, int, int,
                                                      xmlNode*, void *));
     gboolean (*register_callback_full)(cib_t *cib, int call_id, int timeout,
                                        gboolean only_success, void *user_data,
                                        const char *callback_name,
                                        void (*callback)(xmlNode *, int, int,
                                                         xmlNode *, void *),
                                        void (*free_func)(void *));
 
     /*!
      * \brief Set the local CIB manager as the cluster's primary instance
      *
      * \param[in,out] cib           CIB connection
      * \param[in]     call_options  Group of enum cib_call_options flags
      *
      * \return Legacy Pacemaker return code (in particular, pcmk_ok on success)
      */
     int (*set_primary)(cib_t *cib, int call_options);
 
     /*!
      * \brief Set the local CIB manager as a secondary instance
      *
      * \param[in,out] cib           CIB connection
      * \param[in]     call_options  Group of enum cib_call_options flags
      *
      * \return Legacy Pacemaker return code (in particular, pcmk_ok on success)
      */
     int (*set_secondary)(cib_t *cib, int call_options);
 
     /*!
      * \brief Get the given CIB connection's unique client identifier(s)
      *
      * These can be used to check whether this client requested the action that
      * triggered a CIB notification.
      *
      * \param[in]  cib       CIB connection
      * \param[out] async_id  If not \p NULL, where to store asynchronous client
      *                       ID
      * \param[out] sync_id   If not \p NULL, where to store synchronous client
      *                       ID
      *
      * \return Legacy Pacemaker return code
      *
      * \note Some variants may have only one client for both asynchronous and
      *       synchronous requests.
      */
     int (*client_id)(const cib_t *cib, const char **async_id,
                      const char **sync_id);
 
     /*!
      * \brief Initiate an atomic CIB transaction for this client
      *
      * If the client has initiated a transaction and a new request's call
      * options contain \p cib_transaction, the new request is appended to the
      * transaction for later processing.
      *
      * Supported requests are those that meet the following conditions:
      * * can be processed synchronously (with any changes applied to a working
      *   CIB copy)
      * * are not queries
      * * do not involve other nodes
      * * do not affect the state of pacemaker-based itself
      *
      * Currently supported CIB API functions include:
      * * \p bump_epoch()
      * * \p create()
      * * \p erase()
      * * \p modify()
      * * \p remove()
      * * \p replace()
      * * \p upgrade()
      *
      * Because the transaction is atomic, individual requests do not trigger
      * callbacks or notifications when they are processed, and they do not
      * receive output XML. The commit request itself can trigger callbacks and
      * notifications if any are registered.
      *
      * An \c init_transaction() call is always synchronous.
      *
      * \param[in,out] cib           CIB connection
      *
      * \return Legacy Pacemaker return code
      */
     int (*init_transaction)(cib_t *cib);
 
     /*!
      * \brief End and optionally commit this client's CIB transaction
      *
      * When a client commits a transaction, all requests in the transaction are
      * processed in a FIFO manner until either a request fails or all requests
      * have been processed. Changes are applied to a working copy of the CIB.
      * If a request fails, the transaction and working CIB copy are discarded,
      * and an error is returned. If all requests succeed, the working CIB copy
      * replaces the initial CIB copy.
      *
      * Callbacks and notifications can be triggered by the commit request itself
      * but not by the individual requests in a transaction.
      *
      * An \c end_transaction() call with \p commit set to \c false is always
      * synchronous.
      *
      * \param[in,out] cib           CIB connection
      * \param[in]     commit        If \p true, commit transaction; otherwise,
      *                              discard it
      * \param[in]     call_options  Group of <tt>enum cib_call_options</tt>
      *                              flags
      *
      * \return Legacy Pacemaker return code
      */
     int (*end_transaction)(cib_t *cib, bool commit, int call_options);
 
     /*!
      * \brief Set the user as whom all CIB requests via methods will be executed
      *
      * By default, the value of the \c CIB_user environment variable is used if
      * set. Otherwise, the current effective user is used.
      *
      * \param[in,out] cib   CIB connection
      * \param[in]     user  Name of user whose permissions to use when
      *                      processing requests
      */
     void (*set_user)(cib_t *cib, const char *user);
 
     int (*fetch_schemas)(cib_t *cib, xmlNode **output_data, const char *after_ver,
                          int call_options);
 } cib_api_operations_t;
 
 struct cib_s {
+    // NOTE: sbd (as of at least 1.5.2) uses this
     enum cib_state state;
+
     enum cib_conn_type type;
     enum cib_variant variant;
 
     int call_id;
     int call_timeout;
     void *variant_opaque;
     void *delegate_fn;
 
     GList *notify_list;
 
     //! \deprecated This method will be removed in a future release
     void (*op_callback) (const xmlNode *msg, int call_id, int rc,
                          xmlNode *output);
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     cib_api_operations_t *cmds;
 
     xmlNode *transaction;
 
     char *user;
 };
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_CIB_CIB_TYPES__H
diff --git a/include/crm/cib/util.h b/include/crm/cib/util.h
index a86be6149d..b68c061b86 100644
--- a/include/crm/cib/util.h
+++ b/include/crm/cib/util.h
@@ -1,64 +1,65 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CIB_UTIL__H
 #  define PCMK__CRM_CIB_UTIL__H
 
 #include <glib.h>               // gboolean
 #include <libxml/tree.h>        // xmlNode
 #include <crm/cib/cib_types.h>  // cib_t
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* Utility functions */
 xmlNode *createEmptyCib(int cib_epoch);
 
 gboolean cib_version_details(xmlNode * cib, int *admin_epoch, int *epoch, int *updates);
 
 int update_attr_delegate(cib_t * the_cib, int call_options,
                          const char *section, const char *node_uuid,
                          const char *set_type, const char *set_name,
                          const char *attr_id, const char *attr_name,
                          const char *attr_value, gboolean to_console,
                          const char *user_name, const char *node_type);
 
 int find_nvpair_attr_delegate(cib_t * the_cib, const char *attr,
                               const char *section, const char *node_uuid,
                               const char *set_type, const char *set_name,
                               const char *attr_id, const char *attr_name,
                               gboolean to_console, char **value, const char *user_name);
 
 int read_attr_delegate(cib_t * the_cib,
                        const char *section, const char *node_uuid,
                        const char *set_type, const char *set_name,
                        const char *attr_id, const char *attr_name,
                        char **attr_value, gboolean to_console, const char *user_name);
 
 int delete_attr_delegate(cib_t * the_cib, int options,
                          const char *section, const char *node_uuid,
                          const char *set_type, const char *set_name,
                          const char *attr_id, const char *attr_name,
                          const char *attr_value, gboolean to_console, const char *user_name);
 
 int query_node_uuid(cib_t * the_cib, const char *uname, char **uuid, int *is_remote_node);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 int cib_apply_patch_event(xmlNode *event, xmlNode *input, xmlNode **output,
                           int level);
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/cib/util_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/cib_compat.h b/include/crm/cib_compat.h
index 4d028076ee..01f1d6ca78 100644
--- a/include/crm/cib_compat.h
+++ b/include/crm/cib_compat.h
@@ -1,33 +1,34 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CIB_COMPAT__H
 #  define PCMK__CRM_CIB_COMPAT__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated CIB utilities
  * \ingroup core
  * \deprecated Do not include this header directly. The utilities in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Do not use
 #define T_CIB_DIFF_NOTIFY "cib_diff_notify"
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_CIB_COMPAT__H
diff --git a/include/crm/cluster.h b/include/crm/cluster.h
index 1a8cebd1e0..778c4baa3d 100644
--- a/include/crm/cluster.h
+++ b/include/crm/cluster.h
@@ -1,263 +1,265 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CLUSTER__H
 #  define PCMK__CRM_CLUSTER__H
 
 #  include <stdint.h>           // uint32_t, uint64_t
 #  include <glib.h>             // gboolean, GHashTable
 #  include <libxml/tree.h>      // xmlNode
 #  include <crm/common/xml.h>
 #  include <crm/common/util.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #  if SUPPORT_COROSYNC
 #    include <corosync/cpg.h>
 #  endif
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 extern gboolean crm_have_quorum;
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 extern GHashTable *crm_peer_cache;
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 extern GHashTable *crm_remote_peer_cache;
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 extern unsigned long long crm_peer_seq;
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 #define CRM_NODE_LOST      "lost"
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //! \deprecated Do not use (public access will be removed in a future release)
 #define CRM_NODE_MEMBER    "member"
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum crm_join_phase {
     /* @COMPAT: crm_join_nack_quiet can be replaced by crm_node_t:user_data
      *          at a compatibility break.
      */
     //! Not allowed to join, but don't send a nack message
     crm_join_nack_quiet = -2,
 
     crm_join_nack       = -1,
     crm_join_none       = 0,
     crm_join_welcomed   = 1,
     crm_join_integrated = 2,
     crm_join_finalized  = 3,
     crm_join_confirmed  = 4,
 };
 //!@}
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum crm_node_flags {
     /* Node is not a cluster node and should not be considered for cluster
      * membership
      */
     crm_remote_node = (1U << 0),
 
     // Node's cache entry is dirty
     crm_node_dirty  = (1U << 1),
 };
 //!@}
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 typedef struct crm_peer_node_s {
     char *uname;                // Node name as known to cluster
 
     /* @COMPAT This is less than ideal since the value is not a valid XML ID
      * (for Corosync, it's the string equivalent of the node's numeric node ID,
      * but XML IDs can't start with a number) and the three elements should have
      * different IDs.
      *
      * Ideally, we would use something like node-NODEID, node_state-NODEID, and
      * transient_attributes-NODEID as the element IDs. Unfortunately changing it
      * would be impractical due to backward compatibility; older nodes in a
      * rolling upgrade will always write and expect the value in the old format.
      *
      * This is also named poorly, since the value is not a UUID, but at least
      * that can be changed at an API compatibility break.
      */
     /*! Value of the PCMK_XA_ID XML attribute to use with the node's
      * PCMK_XE_NODE, PCMK_XE_NODE_STATE, and PCMK_XE_TRANSIENT_ATTRIBUTES
      * XML elements in the CIB
      */
     char *uuid;
 
     char *state;                // @TODO change to enum
     uint64_t flags;             // Bitmask of crm_node_flags
     uint64_t last_seen;         // Only needed by cluster nodes
     uint32_t processes;         // @TODO most not needed, merge into flags
 
     /* @TODO When we can break public API compatibility, we can make the rest of
      * these members separate structs and use void *cluster_data and
      * void *user_data here instead, to abstract the cluster layer further.
      */
 
     // Currently only needed by corosync stack
     uint32_t id;                // Node ID
     time_t when_lost;           // When CPG membership was last lost
 
     // Only used by controller
     enum crm_join_phase join;
     char *expected;
 
     time_t peer_lost;
     char *conn_host;
 
     time_t when_member;         // Since when node has been a cluster member
     time_t when_online;         // Since when peer has been online in CPG
 } crm_node_t;
 //!@}
 
 // Implementation of pcmk_cluster_t
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 struct crm_cluster_s {
     char *uuid;
     char *uname;
     uint32_t nodeid;
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_cluster_set_destroy_fn() to set this
     void (*destroy) (gpointer);
 
 #  if SUPPORT_COROSYNC
     /* @TODO When we can break public API compatibility, make these members a
      * separate struct and use void *cluster_data here instead, to abstract the
      * cluster layer further.
      */
     struct cpg_name group;
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     /*!
      * \deprecated Call pcmk_cpg_set_deliver_fn() and pcmk_cpg_set_confchg_fn()
      *             to set these
      */
     cpg_callbacks_t cpg;
 
     cpg_handle_t cpg_handle;
 #  endif
 
 };
 //!@}
 
 //! Connection to a cluster layer
 typedef struct crm_cluster_s pcmk_cluster_t;
 
 int pcmk_cluster_connect(pcmk_cluster_t *cluster);
 int pcmk_cluster_disconnect(pcmk_cluster_t *cluster);
 
 pcmk_cluster_t *pcmk_cluster_new(void);
 void pcmk_cluster_free(pcmk_cluster_t *cluster);
 
 int pcmk_cluster_set_destroy_fn(pcmk_cluster_t *cluster, void (*fn)(gpointer));
 #if SUPPORT_COROSYNC
 int pcmk_cpg_set_deliver_fn(pcmk_cluster_t *cluster, cpg_deliver_fn_t fn);
 int pcmk_cpg_set_confchg_fn(pcmk_cluster_t *cluster, cpg_confchg_fn_t fn);
 #endif  // SUPPORT_COROSYNC
 
 /* @COMPAT Make this internal when we can break API backward compatibility. Also
  * evaluate whether we can drop this entirely. Since 2.0.0, we have sent only
  * messages with crm_class_cluster.
  */
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum crm_ais_msg_class {
     crm_class_cluster = 0,
 };
 //!@}
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum crm_ais_msg_types {
     crm_msg_none     = 0,
     crm_msg_ais      = 1,   // Unused
     crm_msg_lrmd     = 2,
     crm_msg_cib      = 3,
     crm_msg_crmd     = 4,
     crm_msg_attrd    = 5,
     crm_msg_stonithd = 6,   // Unused
     crm_msg_te       = 7,   // Unused
     crm_msg_pe       = 8,   // Unused
     crm_msg_stonith_ng = 9,
 };
 //!@}
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum crm_status_type {
     crm_status_uname,
     crm_status_nstate,
     crm_status_processes,
 };
 //!@}
 
 /*!
  * \enum pcmk_cluster_layer
  * \brief Types of cluster layer
  */
 enum pcmk_cluster_layer {
     pcmk_cluster_layer_unknown  = 1,    //!< Unknown cluster layer
     pcmk_cluster_layer_invalid  = 2,    //!< Invalid cluster layer
     pcmk_cluster_layer_corosync = 32,   //!< Corosync Cluster Engine
 };
 
 enum pcmk_cluster_layer pcmk_get_cluster_layer(void);
 const char *pcmk_cluster_layer_text(enum pcmk_cluster_layer layer);
 
 /*
  * \brief Get log-friendly string equivalent of a join phase
  *
  * \param[in] phase  Join phase
  *
  * \return Log-friendly string equivalent of \p phase
  */
 //! \deprecated Do not use (public access will be removed in a future release)
 static inline const char *
 crm_join_phase_str(enum crm_join_phase phase)
 {
     switch (phase) {
         case crm_join_nack_quiet:   return "nack_quiet";
         case crm_join_nack:         return "nack";
         case crm_join_none:         return "none";
         case crm_join_welcomed:     return "welcomed";
         case crm_join_integrated:   return "integrated";
         case crm_join_finalized:    return "finalized";
         case crm_join_confirmed:    return "confirmed";
         default:                    return "invalid";
     }
 }
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/cluster/compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/cluster/compat.h b/include/crm/cluster/compat.h
index 5bacbb50ed..6802edfb5c 100644
--- a/include/crm/cluster/compat.h
+++ b/include/crm/cluster/compat.h
@@ -1,185 +1,194 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CLUSTER_COMPAT__H
 #  define PCMK__CRM_CLUSTER_COMPAT__H
 
 #include <stdint.h>         // uint32_t
 #include <sys/types.h>      // size_t
 
 #include <glib.h>           // gboolean, guint
 #include <libxml/tree.h>    // xmlNode
 
 #if SUPPORT_COROSYNC
 #include <corosync/cpg.h>   // cpg_handle_t
 #endif  // SUPPORT_COROSYNC
 
 #include <crm/cluster.h>    // crm_node_t
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker cluster API
  * \ingroup cluster
  * \deprecated Do not include this header directly. The cluster APIs in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Do not use
 enum crm_get_peer_flags {
     CRM_GET_PEER_CLUSTER   = 0x0001,
     CRM_GET_PEER_REMOTE    = 0x0002,
     CRM_GET_PEER_ANY       = CRM_GET_PEER_CLUSTER|CRM_GET_PEER_REMOTE,
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use \c pcmk_cluster_t instead
 typedef pcmk_cluster_t crm_cluster_t;
 
 //! \deprecated Do not use Pacemaker for cluster node cacheing
 crm_node_t *crm_get_peer(unsigned int id, const char *uname);
 
 //! \deprecated Do not use Pacemaker for cluster node cacheing
 crm_node_t *crm_get_peer_full(unsigned int id, const char *uname, int flags);
 
 //! \deprecated Use stonith_api_kick() from libstonithd instead
 int crm_terminate_member(int nodeid, const char *uname, void *unused);
 
 //! \deprecated Use \c stonith_api_kick() from libstonithd instead
 int crm_terminate_member_no_mainloop(int nodeid, const char *uname,
                                      int *connection);
 
 /*!
  * \deprecated Use
  *             <tt>crm_xml_add(xml, attr, pcmk__cluster_node_uuid(node))</tt>
  *             instead
  */
 void set_uuid(xmlNode *xml, const char *attr, crm_node_t *node);
 
 #if SUPPORT_COROSYNC
 
 //! \deprecated Do not use
 gboolean cluster_connect_cpg(pcmk_cluster_t *cluster);
 
 //! \deprecated Do not use
 void cluster_disconnect_cpg(pcmk_cluster_t *cluster);
 
 //! \deprecated Do not use
 uint32_t get_local_nodeid(cpg_handle_t handle);
 
 //! \deprecated Do not use
 void pcmk_cpg_membership(cpg_handle_t handle,
                          const struct cpg_name *group_name,
                          const struct cpg_address *member_list,
                          size_t member_list_entries,
                          const struct cpg_address *left_list,
                          size_t left_list_entries,
                          const struct cpg_address *joined_list,
                          size_t joined_list_entries);
 
 //! \deprecated Do not use
 gboolean crm_is_corosync_peer_active(const crm_node_t * node);
 
 //! \deprecated Do not use
 gboolean send_cluster_text(enum crm_ais_msg_class msg_class, const char *data,
                            gboolean local, const crm_node_t *node,
                            enum crm_ais_msg_types dest);
 
 //! \deprecated Do not use
 char *pcmk_message_common_cs(cpg_handle_t handle, uint32_t nodeid, uint32_t pid,
                              void *msg, uint32_t *kind, const char **from);
 
 #endif  // SUPPORT_COROSYNC
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use \c pcmk_cluster_connect() instead
 gboolean crm_cluster_connect(pcmk_cluster_t *cluster);
 
 //! \deprecated Use \c pcmk_cluster_disconnect() instead
 void crm_cluster_disconnect(pcmk_cluster_t *cluster);
 
 //! \deprecated Do not use
 int crm_remote_peer_cache_size(void);
 
 //! \deprecated Do not use
 void crm_remote_peer_cache_refresh(xmlNode *cib);
 
 //! \deprecated Do not use
 crm_node_t *crm_remote_peer_get(const char *node_name);
 
 //! \deprecated Do not use
 void crm_remote_peer_cache_remove(const char *node_name);
 
 //! \deprecated Do not use
 gboolean crm_is_peer_active(const crm_node_t *node);
 
 //! \deprecated Do not use
 guint crm_active_peers(void);
 
 //! \deprecated Do not use
 guint reap_crm_member(uint32_t id, const char *name);
 
+// NOTE: sbd (as of at least 1.5.2) uses this enum
 //!@{
 //! \deprecated Use <tt>enum pcmk_cluster_layer</tt> instead
 enum cluster_type_e {
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_cluster_unknown    = pcmk_cluster_layer_unknown,
+
     pcmk_cluster_invalid    = pcmk_cluster_layer_invalid,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_cluster_corosync   = pcmk_cluster_layer_corosync,
 };
 //!@}
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use \c pcmk_cluster_layer_text() instead
 const char *name_for_cluster_type(enum cluster_type_e type);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use \c pcmk_get_cluster_layer() instead
 enum cluster_type_e get_cluster_type(void);
 
 //! \deprecated Use \c pcmk_get_cluster_layer() instead
 gboolean is_corosync_cluster(void);
 
 //! \deprecated Do not use
 void crm_peer_init(void);
 
 //! \deprecated Do not use
 void crm_peer_destroy(void);
 
 //! \deprecated Do not use
 gboolean send_cluster_message(const crm_node_t *node,
                               enum crm_ais_msg_types service,
                               const xmlNode *data, gboolean ordered);
 
 //! \deprecated Do not use
 const char *crm_peer_uuid(crm_node_t *node);
 
 //! \deprecated Do not use
 enum crm_ais_msg_types text2msg_type(const char *text);
 
 //! \deprecated Do not use
 char *get_node_name(uint32_t nodeid);
 
 //! \deprecated Do not use
 const char *get_local_node_name(void);
 
 //! \deprecated Do not use
 void crm_set_autoreap(gboolean enable);
 
 //! \deprecated Do not use
 void crm_set_status_callback(void (*dispatch)(enum crm_status_type,
                                               crm_node_t *, const void *));
 
 //! \deprecated Do not use
 const char *crm_peer_uname(const char *uuid);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK_CLUSTER_COMPAT__H
diff --git a/include/crm/common/ipc.h b/include/crm/common/ipc.h
index a859e25b3a..1e9f9f4d8d 100644
--- a/include/crm/common/ipc.h
+++ b/include/crm/common/ipc.h
@@ -1,240 +1,251 @@
 /*
  * Copyright 2004-2023 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_IPC__H
 #  define PCMK__CRM_COMMON_IPC__H
 
 
 #include <sys/uio.h>
 #include <qb/qbipcc.h>
 #include <crm/common/xml.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief IPC interface to Pacemaker daemons
  *
  * \ingroup core
  */
 
 /*
  * Message creation utilities
  *
  * These are used for both IPC messages and cluster layer messages. However,
  * since this is public API, they stay in this header for backward
  * compatibility.
  */
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 #define create_reply(request, xml_response_data)    \
     create_reply_adv(request, xml_response_data, __func__)
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 xmlNode *create_reply_adv(const xmlNode *request, xmlNode *xml_response_data,
                           const char *origin);
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 #define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from) \
     create_request_adv(task, xml_data, host_to, sys_to, sys_from, uuid_from, \
                        __func__)
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 xmlNode *create_request_adv(const char *task, xmlNode *xml_data,
                             const char *host_to, const char *sys_to,
                             const char *sys_from, const char *uuid_from,
                             const char *origin);
 
 
 /*
  * The library supports two methods of creating IPC connections. The older code
  * allows connecting to any arbitrary IPC name. The newer code only allows
  * connecting to one of the Pacemaker daemons.
  *
  * As daemons are converted to use the new model, the old functions should be
  * considered deprecated for use with those daemons. Once all daemons are
  * converted, the old functions should be officially deprecated as public API
  * and eventually made internal API.
  */
 
 /*
  * Pacemaker daemon IPC
  */
 
 //! Available IPC interfaces
 enum pcmk_ipc_server {
     pcmk_ipc_attrd,         //!< Attribute manager
     pcmk_ipc_based,         //!< CIB manager
     pcmk_ipc_controld,      //!< Controller
     pcmk_ipc_execd,         //!< Executor
     pcmk_ipc_fenced,        //!< Fencer
     pcmk_ipc_pacemakerd,    //!< Launcher
     pcmk_ipc_schedulerd,    //!< Scheduler
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this enum
 //! Possible event types that an IPC event callback can be called for
 enum pcmk_ipc_event {
     pcmk_ipc_event_connect,     //!< Result of asynchronous connection attempt
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_ipc_event_disconnect,  //!< Termination of IPC connection
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_ipc_event_reply,       //!< Daemon's reply to client IPC request
+
     pcmk_ipc_event_notify,      //!< Notification from daemon
 };
 
 //! How IPC replies should be dispatched
 enum pcmk_ipc_dispatch {
     pcmk_ipc_dispatch_main, //!< Attach IPC to GMainLoop for dispatch
     pcmk_ipc_dispatch_poll, //!< Caller will poll and dispatch IPC
     pcmk_ipc_dispatch_sync, //!< Sending a command will wait for any reply
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! Client connection to Pacemaker IPC
 typedef struct pcmk_ipc_api_s pcmk_ipc_api_t;
 
 /*!
  * \brief Callback function type for Pacemaker daemon IPC APIs
  *
  * \param[in,out] api         IPC API connection
  * \param[in]     event_type  The type of event that occurred
  * \param[in]     status      Event status
  * \param[in,out] event_data  Event-specific data
  * \param[in,out] user_data   Caller data provided when callback was registered
  *
  * \note For connection and disconnection events, event_data may be NULL (for
  *       local IPC) or the name of the connected node (for remote IPC, for
  *       daemons that support that). For reply and notify events, event_data is
  *       defined by the specific daemon API.
  */
 typedef void (*pcmk_ipc_callback_t)(pcmk_ipc_api_t *api,
                                     enum pcmk_ipc_event event_type,
                                     crm_exit_t status,
                                     void *event_data, void *user_data);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 int pcmk_new_ipc_api(pcmk_ipc_api_t **api, enum pcmk_ipc_server server);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 void pcmk_free_ipc_api(pcmk_ipc_api_t *api);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 int pcmk_connect_ipc(pcmk_ipc_api_t *api, enum pcmk_ipc_dispatch dispatch_type);
 
 void pcmk_disconnect_ipc(pcmk_ipc_api_t *api);
 
 int pcmk_poll_ipc(const pcmk_ipc_api_t *api, int timeout_ms);
 
 void pcmk_dispatch_ipc(pcmk_ipc_api_t *api);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 void pcmk_register_ipc_callback(pcmk_ipc_api_t *api, pcmk_ipc_callback_t cb,
                                 void *user_data);
 
 const char *pcmk_ipc_name(const pcmk_ipc_api_t *api, bool for_log);
 
 bool pcmk_ipc_is_connected(pcmk_ipc_api_t *api);
 
 int pcmk_ipc_purge_node(pcmk_ipc_api_t *api, const char *node_name,
                         uint32_t nodeid);
 
 
 /*
  * Generic IPC API (to eventually be deprecated as public API and made internal)
  */
 
 /* *INDENT-OFF* */
 enum crm_ipc_flags
 {
     crm_ipc_flags_none      = 0x00000000,
 
     crm_ipc_compressed      = 0x00000001, /* Message has been compressed */
 
     crm_ipc_proxied         = 0x00000100, /* _ALL_ replies to proxied connections need to be sent as events */
     crm_ipc_client_response = 0x00000200, /* A Response is expected in reply */
 
     // These are options for Pacemaker's internal use only (pcmk__ipc_send_*())
     crm_ipc_server_event    = 0x00010000, /* Send an Event instead of a Response */
     crm_ipc_server_free     = 0x00020000, /* Free the iovec after sending */
     crm_ipc_proxied_relay_response = 0x00040000, /* all replies to proxied connections are sent as events, this flag preserves whether the event should be treated as an actual event, or a response.*/
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     crm_ipc_server_info     = 0x00100000, //!< \deprecated Unused
     crm_ipc_server_error    = 0x00200000, //!< \deprecated Unused
 #endif
 };
 /* *INDENT-ON* */
 
 typedef struct crm_ipc_s crm_ipc_t;
 
 crm_ipc_t *crm_ipc_new(const char *name, size_t max_size);
 bool crm_ipc_connect(crm_ipc_t * client);
 void crm_ipc_close(crm_ipc_t * client);
 void crm_ipc_destroy(crm_ipc_t * client);
 void pcmk_free_ipc_event(struct iovec *event);
 
 int crm_ipc_send(crm_ipc_t *client, const xmlNode *message,
                  enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply);
 
 int crm_ipc_get_fd(crm_ipc_t * client);
 bool crm_ipc_connected(crm_ipc_t * client);
 int crm_ipc_ready(crm_ipc_t * client);
 long crm_ipc_read(crm_ipc_t * client);
 const char *crm_ipc_buffer(crm_ipc_t * client);
 uint32_t crm_ipc_buffer_flags(crm_ipc_t * client);
 const char *crm_ipc_name(crm_ipc_t * client);
 unsigned int crm_ipc_default_buffer_size(void);
 
 /*!
  * \brief Check the authenticity of the IPC socket peer process (legacy)
  *
  * If everything goes well, peer's authenticity is verified by the means
  * of comparing against provided referential UID and GID (either satisfies),
  * and the result of this check can be deduced from the return value.
  * As an exception, detected UID of 0 ("root") satisfies arbitrary
  * provided referential daemon's credentials.
  *
  * \param[in]  sock    IPC related, connected Unix socket to check peer of
  * \param[in]  refuid  referential UID to check against
  * \param[in]  refgid  referential GID to check against
  * \param[out] gotpid  to optionally store obtained PID of the peer
  *                     (not available on FreeBSD, special value of 1
  *                     used instead, and the caller is required to
  *                     special case this value respectively)
  * \param[out] gotuid  to optionally store obtained UID of the peer
  * \param[out] gotgid  to optionally store obtained GID of the peer
  *
  * \return 0 if IPC related socket's peer is not authentic given the
  *         referential credentials (see above), 1 if it is,
  *         negative value on error (generally expressing -errno unless
  *         it was zero even on nonhappy path, -pcmk_err_generic is
  *         returned then; no message is directly emitted)
  *
  * \note While this function is tolerant on what constitutes authorized
  *       IPC daemon process (its effective user matches UID=0 or \p refuid,
  *       or at least its group matches \p refgid), either or both (in case
  *       of UID=0) mismatches on the expected credentials of such peer
  *       process \e shall be investigated at the caller when value of 1
  *       gets returned there, since higher-than-expected privileges in
  *       respect to the expected/intended credentials possibly violate
  *       the least privilege principle and may pose an additional risk
  *       (i.e. such accidental inconsistency shall be eventually fixed).
  */
 int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
                                  pid_t *gotpid, uid_t *gotuid, gid_t *gotgid);
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 xmlNode *create_hello_message(const char *uuid, const char *client_name,
                               const char *major_version, const char *minor_version);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/ipc_pacemakerd.h b/include/crm/common/ipc_pacemakerd.h
index 340f9a681c..b34550011f 100644
--- a/include/crm/common/ipc_pacemakerd.h
+++ b/include/crm/common/ipc_pacemakerd.h
@@ -1,79 +1,93 @@
 /*
  * Copyright 2020 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_IPC_PACEMAKERD__H
 #  define PCMK__CRM_COMMON_IPC_PACEMAKERD__H
 
 #include <sys/types.h>       // time_t
 #include <crm/common/ipc.h>  // pcmk_ipc_api_t
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief IPC commands for Pacemakerd
  *
  * \ingroup core
  */
 
+// NOTE: sbd (as of at least 1.5.2) uses this enum
 enum pcmk_pacemakerd_state {
     pcmk_pacemakerd_state_invalid = -1,
     pcmk_pacemakerd_state_init = 0,
     pcmk_pacemakerd_state_starting_daemons,
     pcmk_pacemakerd_state_wait_for_ping,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_pacemakerd_state_running,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_pacemakerd_state_shutting_down,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_pacemakerd_state_shutdown_complete,
+
     pcmk_pacemakerd_state_remote,
     pcmk_pacemakerd_state_max = pcmk_pacemakerd_state_remote,
 };
 
 //! Possible types of pacemakerd replies
 enum pcmk_pacemakerd_api_reply {
     pcmk_pacemakerd_reply_unknown,
+
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     pcmk_pacemakerd_reply_ping,
+
     pcmk_pacemakerd_reply_shutdown,
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this type and some of its members
 /*!
  * Pacemakerd reply passed to event callback
  */
 typedef struct {
     enum pcmk_pacemakerd_api_reply reply_type;
 
     union {
         // pcmk_pacemakerd_reply_ping
         struct {
             const char *sys_from;
             enum pcmk_pacemakerd_state state;
             time_t last_good;
             int status;
         } ping;
         // pcmk_pacemakerd_reply_shutdown
         struct {
             int status;
         } shutdown;
     } data;
 } pcmk_pacemakerd_api_reply_t;
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 int pcmk_pacemakerd_api_ping(pcmk_ipc_api_t *api, const char *ipc_name);
+
 int pcmk_pacemakerd_api_shutdown(pcmk_ipc_api_t *api, const char *ipc_name);
 
 enum pcmk_pacemakerd_state
     pcmk_pacemakerd_api_daemon_state_text2enum(const char *state);
 const char
     *pcmk_pacemakerd_api_daemon_state_enum2text(enum pcmk_pacemakerd_state state);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_IPC_PACEMAKERD__H
diff --git a/include/crm/common/logging.h b/include/crm/common/logging.h
index d23140e5ff..bfc2a5bf7b 100644
--- a/include/crm/common/logging.h
+++ b/include/crm/common/logging.h
@@ -1,420 +1,432 @@
 /*
  * Copyright 2004-2023 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_LOGGING__H
 #  define PCMK__CRM_COMMON_LOGGING__H
 
 #  include <stdio.h>
 #  include <stdint.h>           // uint8_t, uint32_t
 #  include <glib.h>
 #  include <qb/qblog.h>
 #  include <libxml/tree.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Wrappers for and extensions to libqb logging
  * \ingroup core
  */
 
 
 /* Define custom log priorities.
  *
  * syslog(3) uses int for priorities, but libqb's struct qb_log_callsite uses
  * uint8_t, so make sure they fit in the latter.
  */
 
 // Define something even less desired than debug
 #  ifndef LOG_TRACE
 #    define LOG_TRACE   (LOG_DEBUG+1)
 #  endif
 
 // Print message to stdout instead of logging it
 #  ifndef LOG_STDOUT
 #    define LOG_STDOUT  254
 #  endif
 
 // Don't send message anywhere
 #  ifndef LOG_NEVER
 #    define LOG_NEVER   255
 #  endif
 
 /* "Extended information" logging support */
 #ifdef QB_XS
 #  define CRM_XS QB_XS
 #  define crm_extended_logging(t, e) qb_log_ctl((t), QB_LOG_CONF_EXTENDED, (e))
 #else
 #  define CRM_XS "|"
 
 /* A caller might want to check the return value, so we can't define this as a
  * no-op, and we can't simply define it to be 0 because gcc will then complain
  * when the value isn't checked.
  */
 static inline int
 crm_extended_logging(int t, int e)
 {
     return 0;
 }
 #endif
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 extern unsigned int crm_log_level;
 
 // @COMPAT Make internal when we can break API backward compatibility
 //! \deprecated Do not use
 extern unsigned int crm_trace_nonlog;
 
 /*! \deprecated Pacemaker library functions set this when a configuration
  *              error is found, which turns on extra messages at the end of
  *              processing. It should not be used directly and will be removed
  *              from the public C API in a future release.
  */
 extern gboolean crm_config_error;
 
 /*! \deprecated Pacemaker library functions set this when a configuration
  *              warning is found, which turns on extra messages at the end of
  *              processing. It should not be used directly and will be removed
  *              from the public C API in a future release.
  */
 extern gboolean crm_config_warning;
 
 void crm_enable_blackbox(int nsig);
 void crm_disable_blackbox(int nsig);
 void crm_write_blackbox(int nsig, const struct qb_log_callsite *callsite);
 
 void crm_update_callsites(void);
 
 void crm_log_deinit(void);
 
 /*!
  * \brief Initializes the logging system and defaults to the least verbose output level
  *
  * \param[in] entity  If not NULL, will be used as the identity for logging purposes
  * \param[in] argc    The number of command line parameters
  * \param[in] argv    The command line parameter values
  */
 void crm_log_preinit(const char *entity, int argc, char *const *argv);
 gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon,
                       gboolean to_stderr, int argc, char **argv, gboolean quiet);
 
 void crm_log_args(int argc, char **argv);
 void crm_log_output_fn(const char *file, const char *function, int line, int level,
                        const char *prefix, const char *output);
 
 // Log a block of text line by line
 #define crm_log_output(level, prefix, output)   \
     crm_log_output_fn(__FILE__, __func__, __LINE__, level, prefix, output)
 
 void crm_bump_log_level(int argc, char **argv);
 
 void crm_enable_stderr(int enable);
 
 gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /* returns the old value */
 unsigned int set_crm_log_level(unsigned int level);
 
 unsigned int get_crm_log_level(void);
 
 void pcmk_log_xml_as(const char *file, const char *function, uint32_t line,
                      uint32_t tags, uint8_t level, const char *text,
                      const xmlNode *xml);
 
 /*
  * Throughout the macros below, note the leading, pre-comma, space in the
  * various ' , ##args' occurrences to aid portability across versions of 'gcc'.
  * https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros
  */
 #if defined(__clang__)
 #    define CRM_TRACE_INIT_DATA(name)
 #  else
 #    include <assert.h> // required by QB_LOG_INIT_DATA() macro
 #    define CRM_TRACE_INIT_DATA(name) QB_LOG_INIT_DATA(name)
 #endif
 
 /*!
  * \internal
  * \brief Clip log_level to \p uint8_t range
  *
  * \param[in] level  Log level to clip
  *
  * \return 0 if \p level is less than 0, \p UINT8_MAX if \p level is greater
  *         than \p UINT8_MAX, or \p level otherwise
  */
 /* @COMPAT: Make this function internal at a compatibility break. It's used in
  * public macros for now.
  */
 static inline uint8_t
 pcmk__clip_log_level(int level)
 {
     if (level <= 0) {
         return 0;
     }
     if (level >= UINT8_MAX) {
         return UINT8_MAX;
     }
     return level;
 }
 
 /* Using "switch" instead of "if" in these macro definitions keeps
  * static analysis from complaining about constant evaluations
  */
 
 /*!
  * \brief Log a message
  *
  * \param[in] level  Priority at which to log the message
  * \param[in] fmt    printf-style format string literal for message
  * \param[in] args   Any arguments needed by format string
  */
 #  define do_crm_log(level, fmt, args...) do {                              \
         uint8_t _level = pcmk__clip_log_level(level);                       \
                                                                             \
         switch (_level) {                                                   \
             case LOG_STDOUT:                                                \
                 printf(fmt "\n" , ##args);                                  \
                 break;                                                      \
             case LOG_NEVER:                                                 \
                 break;                                                      \
             default:                                                        \
                 qb_log_from_external_source(__func__, __FILE__, fmt,        \
                                             _level, __LINE__, 0 , ##args);  \
                 break;                                                      \
         }                                                                   \
     } while (0)
 
 /*!
  * \brief Log a message that is likely to be filtered out
  *
  * \param[in] level  Priority at which to log the message
  * \param[in] fmt    printf-style format string for message
  * \param[in] args   Any arguments needed by format string
  *
  * \note This does nothing when level is \p LOG_STDOUT.
  */
 #  define do_crm_log_unlikely(level, fmt, args...) do {                     \
         uint8_t _level = pcmk__clip_log_level(level);                       \
                                                                             \
         switch (_level) {                                                   \
             case LOG_STDOUT: case LOG_NEVER:                                \
                 break;                                                      \
             default: {                                                      \
                 static struct qb_log_callsite *trace_cs = NULL;             \
                 if (trace_cs == NULL) {                                     \
                     trace_cs = qb_log_callsite_get(__func__, __FILE__, fmt, \
                                                    _level, __LINE__, 0);    \
                 }                                                           \
                 if (crm_is_callsite_active(trace_cs, _level, 0)) {          \
                     qb_log_from_external_source(__func__, __FILE__, fmt,    \
                                                 _level, __LINE__, 0 ,       \
                                                 ##args);                    \
                 }                                                           \
             }                                                               \
             break;                                                          \
         }                                                                   \
     } while (0)
 
 #  define CRM_LOG_ASSERT(expr) do {					\
         if (!(expr)) {                                                  \
             static struct qb_log_callsite *core_cs = NULL;              \
             if(core_cs == NULL) {                                       \
                 core_cs = qb_log_callsite_get(__func__, __FILE__,       \
                                               "log-assert", LOG_TRACE,  \
                                               __LINE__, 0);             \
             }                                                           \
             crm_abort(__FILE__, __func__, __LINE__, #expr,              \
                       core_cs?core_cs->targets:FALSE, TRUE);            \
         }                                                               \
     } while(0)
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /* 'failure_action' MUST NOT be 'continue' as it will apply to the
  * macro's do-while loop
  */
 #  define CRM_CHECK(expr, failure_action) do {				            \
         if (!(expr)) {                                                  \
             static struct qb_log_callsite *core_cs = NULL;              \
             if (core_cs == NULL) {                                      \
                 core_cs = qb_log_callsite_get(__func__, __FILE__,       \
                                               "check-assert",           \
                                               LOG_TRACE, __LINE__, 0);  \
             }                                                           \
 	        crm_abort(__FILE__, __func__, __LINE__, #expr,	            \
 		        (core_cs? core_cs->targets: FALSE), TRUE);              \
 	        failure_action;						                        \
 	    }								                                \
     } while(0)
 
 /*!
  * \brief Log XML line-by-line in a formatted fashion
  *
  * \param[in] level  Priority at which to log the messages
  * \param[in] text   Prefix for each line
  * \param[in] xml    XML to log
  *
  * \note This does nothing when \p level is \p LOG_STDOUT.
  */
 #  define do_crm_log_xml(level, text, xml) do {                         \
         uint8_t _level = pcmk__clip_log_level(level);                   \
         static struct qb_log_callsite *xml_cs = NULL;                   \
                                                                         \
         switch (_level) {                                               \
             case LOG_STDOUT:                                            \
             case LOG_NEVER:                                             \
                 break;                                                  \
             default:                                                    \
                 if (xml_cs == NULL) {                                   \
                     xml_cs = qb_log_callsite_get(__func__, __FILE__,    \
                                                  "xml-blob", _level,    \
                                                  __LINE__, 0);          \
                 }                                                       \
                 if (crm_is_callsite_active(xml_cs, _level, 0)) {        \
                     pcmk_log_xml_as(__FILE__, __func__, __LINE__, 0,    \
                                     _level, text, (xml));               \
                 }                                                       \
                 break;                                                  \
         }                                                               \
     } while(0)
 
 /*!
  * \brief Log a message as if it came from a different code location
  *
  * \param[in] level     Priority at which to log the message
  * \param[in] file      Source file name to use instead of __FILE__
  * \param[in] function  Source function name to use instead of __func__
  * \param[in] line      Source line number to use instead of __line__
  * \param[in] fmt       printf-style format string literal for message
  * \param[in] args      Any arguments needed by format string
  */
 #  define do_crm_log_alias(level, file, function, line, fmt, args...) do {  \
         uint8_t _level = pcmk__clip_log_level(level);                       \
                                                                             \
         switch (_level) {                                                   \
             case LOG_STDOUT:                                                \
                 printf(fmt "\n" , ##args);                                  \
                 break;                                                      \
             case LOG_NEVER:                                                 \
                 break;                                                      \
             default:                                                        \
                 qb_log_from_external_source(function, file, fmt, _level,    \
                                             line, 0 , ##args);              \
                 break;                                                      \
         }                                                                   \
     } while (0)
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /*!
  * \brief Send a system error message to both the log and stderr
  *
  * \param[in] level  Priority at which to log the message
  * \param[in] fmt    printf-style format string for message
  * \param[in] args   Any arguments needed by format string
  *
  * \deprecated One of the other logging functions should be used with
  *             pcmk_strerror() instead.
  * \note This is a macro, and \p level may be evaluated more than once.
  * \note Because crm_perror() adds the system error message and error number
  *       onto the end of fmt, that information will become extended information
  *       if CRM_XS is used inside fmt and will not show up in syslog.
  */
 #  define crm_perror(level, fmt, args...) do {                              \
         uint8_t _level = pcmk__clip_log_level(level);                       \
                                                                             \
         switch (_level) {                                                   \
             case LOG_NEVER:                                                 \
                 break;                                                      \
             default: {                                                      \
                 const char *err = strerror(errno);                          \
                 if (_level <= crm_log_level) {                              \
                     fprintf(stderr, fmt ": %s (%d)\n" , ##args, err,        \
                             errno);                                         \
                 }                                                           \
                 /* Pass original level arg since do_crm_log() also declares \
                  * _level                                                   \
                  */                                                         \
                 do_crm_log((level), fmt ": %s (%d)" , ##args, err, errno);  \
             }                                                               \
             break;                                                          \
         }                                                                   \
     } while (0)
 
 /*!
  * \brief Log a message with a tag (for use with PCMK_trace_tags)
  *
  * \param[in] level  Priority at which to log the message
  * \param[in] tag    String to tag message with
  * \param[in] fmt    printf-style format string for message
  * \param[in] args   Any arguments needed by format string
  *
  * \note This does nothing when level is LOG_STDOUT.
  */
 #  define crm_log_tag(level, tag, fmt, args...)    do {                     \
         uint8_t _level = pcmk__clip_log_level(level);                       \
                                                                             \
         switch (_level) {                                                   \
             case LOG_STDOUT: case LOG_NEVER:                                \
                 break;                                                      \
             default: {                                                      \
                 static struct qb_log_callsite *trace_tag_cs = NULL;         \
                 int converted_tag = g_quark_try_string(tag);                \
                 if (trace_tag_cs == NULL) {                                 \
                     trace_tag_cs = qb_log_callsite_get(__func__, __FILE__,  \
                                                        fmt, _level,         \
                                                        __LINE__,            \
                                                        converted_tag);      \
                 }                                                           \
                 if (crm_is_callsite_active(trace_tag_cs, _level,            \
                                            converted_tag)) {                \
                     qb_log_from_external_source(__func__, __FILE__, fmt,    \
                                                 _level, __LINE__,           \
                                                 converted_tag , ##args);    \
                 }                                                           \
             }                                                               \
         }                                                                   \
     } while (0)
 
 #  define crm_emerg(fmt, args...)   qb_log(LOG_EMERG,       fmt , ##args)
 #  define crm_crit(fmt, args...)    qb_logt(LOG_CRIT,    0, fmt , ##args)
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define crm_err(fmt, args...)     qb_logt(LOG_ERR,     0, fmt , ##args)
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define crm_warn(fmt, args...)    qb_logt(LOG_WARNING, 0, fmt , ##args)
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define crm_notice(fmt, args...)  qb_logt(LOG_NOTICE,  0, fmt , ##args)
-#  define crm_info(fmt, args...)    qb_logt(LOG_INFO,    0, fmt , ##args)
 
+#  define crm_info(fmt, args...)    qb_logt(LOG_INFO,    0, fmt , ##args)
+                                                //
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define crm_debug(fmt, args...)   do_crm_log_unlikely(LOG_DEBUG, fmt , ##args)
+
 #  define crm_trace(fmt, args...)   do_crm_log_unlikely(LOG_TRACE, fmt , ##args)
 
 #  define crm_log_xml_crit(xml, text)    do_crm_log_xml(LOG_CRIT,    text, xml)
 #  define crm_log_xml_err(xml, text)     do_crm_log_xml(LOG_ERR,     text, xml)
 #  define crm_log_xml_warn(xml, text)    do_crm_log_xml(LOG_WARNING, text, xml)
 #  define crm_log_xml_notice(xml, text)  do_crm_log_xml(LOG_NOTICE,  text, xml)
 #  define crm_log_xml_info(xml, text)    do_crm_log_xml(LOG_INFO,    text, xml)
 #  define crm_log_xml_debug(xml, text)   do_crm_log_xml(LOG_DEBUG,   text, xml)
 #  define crm_log_xml_trace(xml, text)   do_crm_log_xml(LOG_TRACE,   text, xml)
 
 #  define crm_log_xml_explicit(xml, text)  do {                 \
         static struct qb_log_callsite *digest_cs = NULL;        \
         digest_cs = qb_log_callsite_get(                        \
             __func__, __FILE__, text, LOG_TRACE, __LINE__,      \
             crm_trace_nonlog);                                  \
         if (digest_cs && digest_cs->targets) {                  \
             do_crm_log_xml(LOG_TRACE,   text, xml);             \
         }                                                       \
     } while(0)
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/common/logging_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/mainloop.h b/include/crm/common/mainloop.h
index a55bcdf411..12f317708d 100644
--- a/include/crm/common/mainloop.h
+++ b/include/crm/common/mainloop.h
@@ -1,192 +1,202 @@
 /*
  * Copyright 2009-2022 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_MAINLOOP__H
 #  define PCMK__CRM_COMMON_MAINLOOP__H
 
 #  include <signal.h> // sighandler_t
 #  include <glib.h>
 #  include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Wrappers for and extensions to glib mainloop
  * \ingroup core
  */
 
 enum mainloop_child_flags {
     /* don't kill pid group on timeout, only kill the pid */
     mainloop_leave_pid_group = 0x01,
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 typedef struct trigger_s crm_trigger_t;
+
 typedef struct mainloop_io_s mainloop_io_t;
 typedef struct mainloop_child_s mainloop_child_t;
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 typedef struct mainloop_timer_s mainloop_timer_t;
 
 void mainloop_cleanup(void);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 crm_trigger_t *mainloop_add_trigger(int priority, int (*dispatch) (gpointer user_data),
                                     gpointer userdata);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 void mainloop_set_trigger(crm_trigger_t * source);
 
 void mainloop_trigger_complete(crm_trigger_t * trig);
 
 gboolean mainloop_destroy_trigger(crm_trigger_t * source);
 
 #  ifndef HAVE_SIGHANDLER_T
 typedef void (*sighandler_t)(int);
 #  endif
 
 sighandler_t crm_signal_handler(int sig, sighandler_t dispatch);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 gboolean mainloop_add_signal(int sig, void (*dispatch) (int sig));
 
 gboolean mainloop_destroy_signal(int sig);
 
 bool mainloop_timer_running(mainloop_timer_t *t);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 void mainloop_timer_start(mainloop_timer_t *t);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 void mainloop_timer_stop(mainloop_timer_t *t);
 
 guint mainloop_timer_set_period(mainloop_timer_t *t, guint period_ms);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 mainloop_timer_t *mainloop_timer_add(const char *name, guint period_ms, bool repeat, GSourceFunc cb, void *userdata);
 
 void mainloop_timer_del(mainloop_timer_t *t);
 
 
 #  include <crm/common/ipc.h>
 #  include <qb/qbipcs.h>
 
 struct ipc_client_callbacks {
     /*!
      * \brief Dispatch function for an IPC connection used as mainloop source
      *
      * \param[in] buffer    Message read from IPC connection
      * \param[in] length    Number of bytes in \p buffer
      * \param[in] userdata  User data passed when creating mainloop source
      *
      * \return Negative value to remove source, anything else to keep it
      */
     int (*dispatch) (const char *buffer, ssize_t length, gpointer userdata);
 
     /*!
      * \brief Destroy function for mainloop IPC connection client data
      *
      * \param[in,out] userdata  User data passed when creating mainloop source
      */
     void (*destroy) (gpointer userdata);
 };
 
 qb_ipcs_service_t *mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
                                            struct qb_ipcs_service_handlers *callbacks);
 
 /*!
  * \brief Start server-side API end-point, hooked into the internal event loop
  *
  * \param[in] name    name of the IPC end-point ("address" for the client)
  * \param[in] type    selects libqb's IPC back-end (or use #QB_IPC_NATIVE)
  * \param[in] callbacks  defines libqb's IPC service-level handlers
  * \param[in] priority  priority relative to other events handled in the
  *                      abstract handling loop, use #QB_LOOP_MED when unsure
  *
  * \return libqb's opaque handle to the created service abstraction
  *
  * \note For portability concerns, do not use this function if you keep
  *       \p priority as #QB_LOOP_MED, stick with #mainloop_add_ipc_server
  *       (with exactly such semantics) instead (once you link with this new
  *       symbol employed, you can't downgrade the library freely anymore).
  *
  * \note The intended effect will only get fully reflected when run-time
  *       linked to patched libqb: https://github.com/ClusterLabs/libqb/pull/352
  */
 qb_ipcs_service_t *mainloop_add_ipc_server_with_prio(const char *name,
                                                     enum qb_ipc_type type,
                                                     struct qb_ipcs_service_handlers *callbacks,
                                                     enum qb_loop_priority prio);
 
 void mainloop_del_ipc_server(qb_ipcs_service_t * server);
 
 mainloop_io_t *mainloop_add_ipc_client(const char *name, int priority, size_t max_size,
                                        void *userdata, struct ipc_client_callbacks *callbacks);
 
 void mainloop_del_ipc_client(mainloop_io_t * client);
 
 crm_ipc_t *mainloop_get_ipc_client(mainloop_io_t * client);
 
 struct mainloop_fd_callbacks {
     /*!
      * \brief Dispatch function for mainloop file descriptor with data ready
      *
      * \param[in,out] userdata  User data passed when creating mainloop source
      *
      * \return Negative value to remove source, anything else to keep it
      */
     int (*dispatch) (gpointer userdata);
 
     /*!
      * \brief Destroy function for mainloop file descriptor client data
      *
      * \param[in,out] userdata  User data passed when creating mainloop source
      */
     void (*destroy) (gpointer userdata);
 };
 
 mainloop_io_t *mainloop_add_fd(const char *name, int priority, int fd, void *userdata,
                                struct mainloop_fd_callbacks *callbacks);
 
 void mainloop_del_fd(mainloop_io_t * client);
 
 /*
  * Create a new tracked process
  * To track a process group, use -pid
  */
 void mainloop_child_add(pid_t pid,
                         int timeout,
                         const char *desc,
                         void *userdata,
                         void (*callback) (mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode));
 
 void mainloop_child_add_with_flags(pid_t pid,
                         int timeout,
                         const char *desc,
                         void *userdata,
                         enum mainloop_child_flags,
                         void (*callback) (mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode));
 
 void *mainloop_child_userdata(mainloop_child_t * child);
 int mainloop_child_timeout(mainloop_child_t * child);
 const char *mainloop_child_name(mainloop_child_t * child);
 
 pid_t mainloop_child_pid(mainloop_child_t * child);
 void mainloop_clear_child_userdata(mainloop_child_t * child);
 gboolean mainloop_child_kill(pid_t pid);
 
 void pcmk_quit_main_loop(GMainLoop *mloop, unsigned int n);
 void pcmk_drain_main_loop(GMainLoop *mloop, guint timer_ms,
                           bool (*check)(guint));
 
 #  define G_PRIORITY_MEDIUM (G_PRIORITY_HIGH/2)
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/common/mainloop_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/nodes.h b/include/crm/common/nodes.h
index a4f1977002..fe0594a629 100644
--- a/include/crm/common/nodes.h
+++ b/include/crm/common/nodes.h
@@ -1,219 +1,230 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_NODES__H
 #  define PCMK__CRM_COMMON_NODES__H
 
 #include <stdbool.h>                    // bool
 #include <glib.h>                       // gboolean, GList, GHashTable
 
 #include <crm/common/scheduler_types.h> // pcmk_resource_t, pcmk_scheduler_t
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*!
  * \file
  * \brief Scheduler API for nodes
  * \ingroup core
  */
 
 // Special node attributes
 
 #define PCMK_NODE_ATTR_MAINTENANCE          "maintenance"
 #define PCMK_NODE_ATTR_STANDBY              "standby"
 #define PCMK_NODE_ATTR_TERMINATE            "terminate"
 
 
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum node_type { // Possible node types
     pcmk_node_variant_cluster  = 1,     // Cluster layer node
     pcmk_node_variant_remote   = 2,     // Pacemaker Remote node
 
     node_ping   = 0,                    // deprecated
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     node_member = pcmk_node_variant_cluster,
     node_remote = pcmk_node_variant_remote,
 #endif
 };
 //!@}
 
 // When to probe a resource on a node (as specified in location constraints)
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 enum pe_discover_e {
     pcmk_probe_always       = 0,    // Always probe resource on node
     pcmk_probe_never        = 1,    // Never probe resource on node
     pcmk_probe_exclusive    = 2,    // Probe only on designated nodes
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     pe_discover_always      = pcmk_probe_always,
     pe_discover_never       = pcmk_probe_never,
     pe_discover_exclusive   = pcmk_probe_exclusive,
 #endif
 };
 //!@}
 
 // Basic node information (all node objects for the same node share this)
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 struct pe_node_shared_s {
     const char *id;             // Node ID at the cluster layer
     const char *uname;          // Node name in cluster
     enum node_type type;        // Node variant
 
     // @TODO Convert these into a flag group
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_node_is_online() instead
     gboolean online;            // Whether online
 
     gboolean standby;           // Whether in standby mode
     gboolean standby_onfail;    // Whether in standby mode due to on-fail
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_node_is_pending() instead
     gboolean pending;           // Whether controller membership is pending
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call !pcmk_node_is_clean() instead
     gboolean unclean;           // Whether node requires fencing
 
     gboolean unseen;            // Whether node has never joined cluster
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_node_is_shutting_down() instead
     gboolean shutdown;          // Whether shutting down
+
     gboolean expected_up;       // Whether expected join state is member
     gboolean is_dc;             // Whether node is cluster's DC
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_node_is_in_maintenance() instead
     gboolean maintenance;       // Whether in maintenance mode
 
     gboolean rsc_discovery_enabled; // Whether probes are allowed on node
 
     /*
      * Whether this is a guest node whose guest resource must be recovered or a
      * remote node that must be fenced
      */
     gboolean remote_requires_reset;
 
     /*
      * Whether this is a Pacemaker Remote node that was fenced since it was last
      * connected by the cluster
      */
     gboolean remote_was_fenced;
 
     /*
      * Whether this is a Pacemaker Remote node previously marked in its
      * node state as being in maintenance mode
      */
     gboolean remote_maintenance;
 
     gboolean unpacked;              // Whether node history has been unpacked
 
     /*
      * Number of resources active on this node (valid after CIB status section
      * has been unpacked, as long as pcmk_sched_no_counts was not set)
      */
     int num_resources;
 
     // Remote connection resource for node, if it is a Pacemaker Remote node
     pcmk_resource_t *remote_rsc;
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
+    // \deprecated Call pcmk_foreach_active_resource() instead
     GList *running_rsc;             // List of resources active on node
+
     GList *allocated_rsc;           // List of resources assigned to node
     GHashTable *attrs;              // Node attributes
     GHashTable *utilization;        // Node utilization attributes
     GHashTable *digest_cache;       // Cache of calculated resource digests
 
     /*
      * Sum of priorities of all resources active on node and on any guest nodes
      * connected to this node, with +1 for promoted instances (used to compare
      * nodes for PCMK_OPT_PRIORITY_FENCING_DELAY)
      */
     int priority;
 
     pcmk_scheduler_t *data_set;     // Cluster that node is part of
 };
 //!@}
 
 // Implementation of pcmk_node_t
 // @COMPAT Make contents internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 struct pe_node_s {
     int weight;         // Node score for a given resource
     gboolean fixed;     // \deprecated Do not use
     int count;          // Counter reused by assignment and promotion code
+
+    // NOTE: sbd (as of at least 1.5.2) uses this
     struct pe_node_shared_s *details;   // Basic node information
 
     // @COMPAT This should be enum pe_discover_e
     int rsc_discover_mode;              // Probe mode (enum pe_discover_e)
 };
 //!@}
 
 bool pcmk_node_is_online(const pcmk_node_t *node);
 bool pcmk_node_is_pending(const pcmk_node_t *node);
 bool pcmk_node_is_clean(const pcmk_node_t *node);
 bool pcmk_node_is_shutting_down(const pcmk_node_t *node);
 bool pcmk_node_is_in_maintenance(const pcmk_node_t *node);
 
 bool pcmk_foreach_active_resource(pcmk_node_t *node,
                                   bool (*fn)(pcmk_resource_t *, void *),
                                   void *user_data);
 /*!
  * \internal
  * \brief Return a string suitable for logging as a node name
  *
  * \param[in] node  Node to return a node name string for
  *
  * \return Node name if available, otherwise node ID if available,
  *         otherwise "unspecified node" if node is NULL or "unidentified node"
  *         if node has neither a name nor ID.
  */
 static inline const char *
 pcmk__node_name(const pcmk_node_t *node)
 {
     if (node == NULL) {
         return "unspecified node";
 
     } else if (node->details->uname != NULL) {
         return node->details->uname;
 
     } else if (node->details->id != NULL) {
         return node->details->id;
 
     } else {
         return "unidentified node";
     }
 }
 
 /*!
  * \internal
  * \brief Check whether two node objects refer to the same node
  *
  * \param[in] node1  First node object to compare
  * \param[in] node2  Second node object to compare
  *
  * \return true if \p node1 and \p node2 refer to the same node
  */
 static inline bool
 pcmk__same_node(const pcmk_node_t *node1, const pcmk_node_t *node2)
 {
     return (node1 != NULL) && (node2 != NULL)
            && (node1->details == node2->details);
 }
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_NODES__H
diff --git a/include/crm/common/resources.h b/include/crm/common/resources.h
index c335b76bb2..29f1b7e480 100644
--- a/include/crm/common/resources.h
+++ b/include/crm/common/resources.h
@@ -1,500 +1,502 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_RESOURCES__H
 #  define PCMK__CRM_COMMON_RESOURCES__H
 
 #include <stdbool.h>                    // bool
 #include <sys/types.h>                  // time_t
 #include <libxml/tree.h>                // xmlNode
 #include <glib.h>                       // gboolean, guint, GList, GHashTable
 
 #include <crm/common/roles.h>           // enum rsc_role_e
 #include <crm/common/scheduler_types.h> // pcmk_resource_t, etc.
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*!
  * \file
  * \brief Scheduler API for resources
  * \ingroup core
  */
 
 // Resource variants supported by Pacemaker
 //!@{
 //! \deprecated Do not use
 enum pe_obj_types {
     // Order matters: some code compares greater or lesser than
     pcmk_rsc_variant_unknown    = -1,   // Unknown resource variant
     pcmk_rsc_variant_primitive  = 0,    // Primitive resource
     pcmk_rsc_variant_group      = 1,    // Group resource
     pcmk_rsc_variant_clone      = 2,    // Clone resource
     pcmk_rsc_variant_bundle     = 3,    // Bundle resource
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     pe_unknown      = pcmk_rsc_variant_unknown,
     pe_native       = pcmk_rsc_variant_primitive,
     pe_group        = pcmk_rsc_variant_group,
     pe_clone        = pcmk_rsc_variant_clone,
     pe_container    = pcmk_rsc_variant_bundle,
 #endif
 };
 
 // What resource needs before it can be recovered from a failed node
 enum rsc_start_requirement {
     pcmk_requires_nothing   = 0,    // Resource can be recovered immediately
     pcmk_requires_quorum    = 1,    // Resource can be recovered if quorate
     pcmk_requires_fencing   = 2,    // Resource can be recovered after fencing
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     rsc_req_nothing         = pcmk_requires_nothing,
     rsc_req_quorum          = pcmk_requires_quorum,
     rsc_req_stonith         = pcmk_requires_fencing,
 #endif
 };
 
 // How to recover a resource that is incorrectly active on multiple nodes
 enum rsc_recovery_type {
     pcmk_multiply_active_restart    = 0,    // Stop on all, start on desired
     pcmk_multiply_active_stop       = 1,    // Stop on all and leave stopped
     pcmk_multiply_active_block      = 2,    // Do nothing to resource
     pcmk_multiply_active_unexpected = 3,    // Stop unexpected instances
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     recovery_stop_start             = pcmk_multiply_active_restart,
     recovery_stop_only              = pcmk_multiply_active_stop,
     recovery_block                  = pcmk_multiply_active_block,
     recovery_stop_unexpected        = pcmk_multiply_active_unexpected,
 #endif
 };
 
 // Resource scheduling flags
 enum pcmk_rsc_flags {
     // No resource flags set (compare with equality rather than bit set)
     pcmk_no_rsc_flags               = 0ULL,
 
     // Whether resource has been removed from the configuration
     pcmk_rsc_removed                = (1ULL << 0),
 
     // Whether resource is managed
     pcmk_rsc_managed                = (1ULL << 1),
 
     // Whether resource is blocked from further action
     pcmk_rsc_blocked                = (1ULL << 2),
 
     // Whether resource has been removed but has a container
     pcmk_rsc_removed_filler         = (1ULL << 3),
 
     // Whether resource has clone notifications enabled
     pcmk_rsc_notify                 = (1ULL << 4),
 
     // Whether resource is not an anonymous clone instance
     pcmk_rsc_unique                 = (1ULL << 5),
 
     // Whether resource's class is "stonith"
     pcmk_rsc_fence_device           = (1ULL << 6),
 
     // Whether resource can be promoted and demoted
     pcmk_rsc_promotable             = (1ULL << 7),
 
     // Whether resource has not yet been assigned to a node
     pcmk_rsc_unassigned             = (1ULL << 8),
 
     // Whether resource is in the process of being assigned to a node
     pcmk_rsc_assigning              = (1ULL << 9),
 
     // Whether resource is in the process of modifying allowed node scores
     pcmk_rsc_updating_nodes         = (1ULL << 10),
 
     // Whether resource is in the process of scheduling actions to restart
     pcmk_rsc_restarting             = (1ULL << 11),
 
     // Whether resource must be stopped (instead of demoted) if it is failed
     pcmk_rsc_stop_if_failed         = (1ULL << 12),
 
     // Whether a reload action has been scheduled for resource
     pcmk_rsc_reload                 = (1ULL << 13),
 
     // Whether resource is a remote connection allowed to run on a remote node
     pcmk_rsc_remote_nesting_allowed = (1ULL << 14),
 
     // Whether resource has \c PCMK_META_CRITICAL meta-attribute enabled
     pcmk_rsc_critical               = (1ULL << 15),
 
     // Whether resource is considered failed
     pcmk_rsc_failed                 = (1ULL << 16),
 
     // Flag for non-scheduler code to use to detect recursion loops
     pcmk_rsc_detect_loop            = (1ULL << 17),
 
     // \deprecated Do not use
     pcmk_rsc_runnable               = (1ULL << 18),
 
     // Whether resource has pending start action in history
     pcmk_rsc_start_pending          = (1ULL << 19),
 
     // \deprecated Do not use
     pcmk_rsc_starting               = (1ULL << 20),
 
     // \deprecated Do not use
     pcmk_rsc_stopping               = (1ULL << 21),
 
     /*
      * Whether resource is multiply active with recovery set to
      * \c PCMK_VALUE_STOP_UNEXPECTED
      */
     pcmk_rsc_stop_unexpected        = (1ULL << 22),
 
     // Whether resource is allowed to live-migrate
     pcmk_rsc_migratable             = (1ULL << 23),
 
     // Whether resource has an ignorable failure
     pcmk_rsc_ignore_failure         = (1ULL << 24),
 
     // Whether resource is an implicit container resource for a bundle replica
     pcmk_rsc_replica_container      = (1ULL << 25),
 
     // Whether resource, its node, or entire cluster is in maintenance mode
     pcmk_rsc_maintenance            = (1ULL << 26),
 
     // \deprecated Do not use
     pcmk_rsc_has_filler             = (1ULL << 27),
 
     // Whether resource can be started or promoted only on quorate nodes
     pcmk_rsc_needs_quorum           = (1ULL << 28),
 
     // Whether resource requires fencing before recovery if on unclean node
     pcmk_rsc_needs_fencing          = (1ULL << 29),
 
     // Whether resource can be started or promoted only on unfenced nodes
     pcmk_rsc_needs_unfencing        = (1ULL << 30),
 };
 //!@}
 
 //! Search options for resources (exact resource ID always matches)
 enum pe_find {
     //! Also match clone instance ID from resource history
     pcmk_rsc_match_history          = (1 << 0),
 
     //! Also match anonymous clone instances by base name
     pcmk_rsc_match_anon_basename    = (1 << 1),
 
     //! Match only clones and their instances, by either clone or instance ID
     pcmk_rsc_match_clone_only       = (1 << 2),
 
     //! If matching by node, compare current node instead of assigned node
     pcmk_rsc_match_current_node     = (1 << 3),
 
     //! \deprecated Do not use
     pe_find_inactive                = (1 << 4),
 
     //! Match clone instances (even unique) by base name as well as exact ID
     pcmk_rsc_match_basename         = (1 << 5),
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     //! \deprecated Use pcmk_rsc_match_history instead
     pe_find_renamed     = pcmk_rsc_match_history,
 
     //! \deprecated Use pcmk_rsc_match_anon_basename instead
     pe_find_anon        = pcmk_rsc_match_anon_basename,
 
     //! \deprecated Use pcmk_rsc_match_clone_only instead
     pe_find_clone       = pcmk_rsc_match_clone_only,
 
     //! \deprecated Use pcmk_rsc_match_current_node instead
     pe_find_current     = pcmk_rsc_match_current_node,
 
     //! \deprecated Use pcmk_rsc_match_basename instead
     pe_find_any         = pcmk_rsc_match_basename,
 #endif
 };
 
 //!@{
 //! \deprecated Do not use
 enum pe_restart {
     pe_restart_restart,
     pe_restart_ignore,
 };
 
 enum pe_print_options {
     pe_print_log            = (1 << 0),
     pe_print_html           = (1 << 1),
     pe_print_ncurses        = (1 << 2),
     pe_print_printf         = (1 << 3),
     pe_print_dev            = (1 << 4),  // Ignored
     pe_print_details        = (1 << 5),  // Ignored
     pe_print_max_details    = (1 << 6),  // Ignored
     pe_print_rsconly        = (1 << 7),
     pe_print_ops            = (1 << 8),
     pe_print_suppres_nl     = (1 << 9),
     pe_print_xml            = (1 << 10),
     pe_print_brief          = (1 << 11),
     pe_print_pending        = (1 << 12),
     pe_print_clone_details  = (1 << 13),
     pe_print_clone_active   = (1 << 14), // Print clone instances only if active
     pe_print_implicit       = (1 << 15)  // Print implicitly created resources
 };
 //!@}
 
 // Resource assignment methods (implementation defined by libpacemaker)
 //! \deprecated Do not use (public access will be removed in a future release)
 typedef struct resource_alloc_functions_s pcmk_assignment_methods_t;
 
 // Resource object methods
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 typedef struct resource_object_functions_s {
     /*
      * \brief Parse variant-specific resource XML from CIB into struct members
      *
      * \param[in,out] rsc        Partially unpacked resource
      * \param[in,out] scheduler  Scheduler data
      *
      * \return TRUE if resource was unpacked successfully, otherwise FALSE
      */
     gboolean (*unpack)(pcmk_resource_t *rsc, pcmk_scheduler_t *scheduler);
 
     /*
      * \brief Search for a resource ID in a resource and its children
      *
      * \param[in] rsc      Search this resource and its children
      * \param[in] id       Search for this resource ID
      * \param[in] on_node  If not NULL, limit search to resources on this node
      * \param[in] flags    Group of enum pe_find flags
      *
      * \return Resource that matches search criteria if any, otherwise NULL
      */
     pcmk_resource_t *(*find_rsc)(pcmk_resource_t *rsc, const char *search,
                                  const pcmk_node_t *node, int flags);
 
     /*
      * \brief Get value of a resource instance attribute
      *
      * \param[in,out] rsc        Resource to check
      * \param[in]     node       Node to use to evaluate rules
      * \param[in]     create     Ignored
      * \param[in]     name       Name of instance attribute to check
      * \param[in,out] scheduler  Scheduler data
      *
      * \return Value of requested attribute if available, otherwise NULL
      * \note The caller is responsible for freeing the result using free().
      */
     char *(*parameter)(pcmk_resource_t *rsc, pcmk_node_t *node, gboolean create,
                        const char *name, pcmk_scheduler_t *scheduler);
 
     // \deprecated Do not use
     void (*print)(pcmk_resource_t *rsc, const char *pre_text, long options,
                   void *print_data);
 
     /*
      * \brief Check whether a resource is active
      *
      * \param[in] rsc  Resource to check
      * \param[in] all  If \p rsc is collective, all instances must be active
      *
      * \return TRUE if \p rsc is active, otherwise FALSE
      */
     gboolean (*active)(pcmk_resource_t *rsc, gboolean all);
 
     /*
      * \brief Get resource's current or assigned role
      *
      * \param[in] rsc      Resource to check
      * \param[in] current  If TRUE, check current role, otherwise assigned role
      *
      * \return Current or assigned role of \p rsc
      */
     enum rsc_role_e (*state)(const pcmk_resource_t *rsc, gboolean current);
 
     /*
      * \brief List nodes where a resource (or any of its children) is
      *
      * \param[in]  rsc      Resource to check
      * \param[out] list     List to add result to
      * \param[in]  current  If 0, list nodes where \p rsc is assigned;
      *                      if 1, where active; if 2, where active or pending
      *
      * \return If list contains only one node, that node, otherwise NULL
      */
     pcmk_node_t *(*location)(const pcmk_resource_t *rsc, GList **list,
                              int current);
 
     /*
      * \brief Free all memory used by a resource
      *
      * \param[in,out] rsc  Resource to free
      */
     void (*free)(pcmk_resource_t *rsc);
 
     /*
      * \brief Increment cluster's instance counts for a resource
      *
      * Given a resource, increment its cluster's ninstances, disabled_resources,
      * and blocked_resources counts for the resource and its descendants.
      *
      * \param[in,out] rsc  Resource to count
      */
     void (*count)(pcmk_resource_t *rsc);
 
     /*
      * \brief Check whether a given resource is in a list of resources
      *
      * \param[in] rsc           Resource ID to check for
      * \param[in] only_rsc      List of resource IDs to check
      * \param[in] check_parent  If TRUE, check top ancestor as well
      *
      * \return TRUE if \p rsc, its top parent if requested, or '*' is in
      *         \p only_rsc, otherwise FALSE
      */
     gboolean (*is_filtered)(const pcmk_resource_t *rsc, GList *only_rsc,
                             gboolean check_parent);
 
     /*
      * \brief Find a node (and optionally count all) where resource is active
      *
      * \param[in]  rsc          Resource to check
      * \param[out] count_all    If not NULL, set this to count of active nodes
      * \param[out] count_clean  If not NULL, set this to count of clean nodes
      *
      * \return A node where the resource is active, preferring the source node
      *         if the resource is involved in a partial migration, or a clean,
      *         online node if the resource's \c PCMK_META_REQUIRES is
      *         \c PCMK_VALUE_QUORUM or \c PCMK_VALUE_NOTHING, otherwise \c NULL.
      */
     pcmk_node_t *(*active_node)(const pcmk_resource_t *rsc,
                                 unsigned int *count_all,
                                 unsigned int *count_clean);
 
     /*
      * \brief Get maximum resource instances per node
      *
      * \param[in] rsc  Resource to check
      *
      * \return Maximum number of \p rsc instances that can be active on one node
      */
     unsigned int (*max_per_node)(const pcmk_resource_t *rsc);
 } pcmk_rsc_methods_t;
 //!@}
 
 // Implementation of pcmk_resource_t
 // @COMPAT Make this internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 struct pe_resource_s {
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_resource_id() instead
     char *id;                           // Resource ID in configuration
 
     char *clone_name;                   // Resource instance ID in history
 
     // Resource configuration (possibly expanded from template)
     xmlNode *xml;
 
     // Original resource configuration, if using template
     xmlNode *orig_xml;
 
     // Configuration of resource operations (possibly expanded from template)
     xmlNode *ops_xml;
 
     pcmk_scheduler_t *cluster;          // Cluster that resource is part of
     pcmk_resource_t *parent;            // Resource's parent resource, if any
     enum pe_obj_types variant;          // Resource variant
     void *variant_opaque;               // Variant-specific (and private) data
     pcmk_rsc_methods_t *fns;            // Resource object methods
     pcmk_assignment_methods_t *cmds;    // Resource assignment methods
 
     enum rsc_recovery_type recovery_type;   // How to recover if failed
 
     enum pe_restart restart_type;   // \deprecated Do not use
     int priority;                   // Configured priority
     int stickiness;                 // Extra preference for current node
     int sort_index;                 // Promotion score on assigned node
     int failure_timeout;            // Failure timeout
     int migration_threshold;        // Migration threshold
     guint remote_reconnect_ms;      // Retry interval for remote connections
     char *pending_task;             // Pending action in history, if any
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_resource_is_managed() instead
     unsigned long long flags;       // Group of enum pcmk_rsc_flags
 
     // @TODO Merge these into flags
     gboolean is_remote_node;        // Whether this is a remote connection
     gboolean exclusive_discover;    // Whether exclusive probing is enabled
 
     /* Pay special attention to whether you want to use rsc_cons_lhs and
      * rsc_cons directly, which include only colocations explicitly involving
      * this resource, or call libpacemaker's pcmk__with_this_colocations() and
      * pcmk__this_with_colocations() functions, which may return relevant
      * colocations involving the resource's ancestors as well.
      */
 
     GList *rsc_cons_lhs;      // Colocations of other resources with this one
     GList *rsc_cons;          // Colocations of this resource with others
     GList *rsc_location;      // Location constraints for resource
     GList *actions;           // Actions scheduled for resource
     GList *rsc_tickets;       // Ticket constraints for resource
 
     pcmk_node_t *allocated_to;  // Node resource is assigned to
 
     // The destination node, if migrate_to completed but migrate_from has not
     pcmk_node_t *partial_migration_target;
 
     // The source node, if migrate_to completed but migrate_from has not
     pcmk_node_t *partial_migration_source;
 
     // Nodes where resource may be active
     GList *running_on;
 
     // Nodes where resource has been probed (key is node ID, not name)
     GHashTable *known_on;
 
     // Nodes where resource may run (key is node ID, not name)
     GHashTable *allowed_nodes;
 
     enum rsc_role_e role;           // Resource's current role
     enum rsc_role_e next_role;      // Resource's scheduled next role
 
     GHashTable *meta;               // Resource's meta-attributes
     GHashTable *parameters;         // \deprecated Use pe_rsc_params() instead
     GHashTable *utilization;        // Resource's utilization attributes
 
     GList *children;                // Resource's child resources, if any
 
     // Source nodes where stop is needed after migrate_from and migrate_to
     GList *dangling_migrations;
 
     pcmk_resource_t *container;     // Resource containing this one, if any
     GList *fillers;                 // Resources contained by this one, if any
 
     // @COMPAT These should be made const at next API compatibility break
     pcmk_node_t *pending_node;      // Node on which pending_task is happening
     pcmk_node_t *lock_node;         // Resource shutdown-locked to this node
 
     time_t lock_time;               // When shutdown lock started
 
     /*
      * Resource parameters may have node-attribute-based rules, which means the
      * values can vary by node. This table has node names as keys and parameter
      * name/value tables as values. Use pe_rsc_params() to get the table for a
      * given node rather than use this directly.
      */
     GHashTable *parameter_cache;
 };
 //!@}
 
 const char *pcmk_resource_id(const pcmk_resource_t *rsc);
 bool pcmk_resource_is_managed(const pcmk_resource_t *rsc);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_RESOURCES__H
diff --git a/include/crm/common/results.h b/include/crm/common/results.h
index 9ebd04a0f8..ac5b641954 100644
--- a/include/crm/common/results.h
+++ b/include/crm/common/results.h
@@ -1,394 +1,419 @@
 /*
  * Copyright 2012-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 #ifndef PCMK__CRM_COMMON_RESULTS__H
 #  define PCMK__CRM_COMMON_RESULTS__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*!
  * \file
  * \brief Function and executable result codes
  * \ingroup core
  */
 
 // Lifted from config.h
 /* The _Noreturn keyword of C11.  */
 #ifndef _Noreturn
 # if (defined __cplusplus \
       && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
           || (defined _MSC_VER && 1900 <= _MSC_VER)))
 #  define _Noreturn [[noreturn]]
 # elif ((!defined __cplusplus || defined __clang__) \
         && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0)  \
             || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
    /* _Noreturn works as-is.  */
 # elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
 #  define _Noreturn __attribute__ ((__noreturn__))
 # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0)
 #  define _Noreturn __declspec (noreturn)
 # else
 #  define _Noreturn
 # endif
 #endif
 
 #  define CRM_ASSERT(expr) do {                                              \
         if (!(expr)) {                                                       \
             crm_abort(__FILE__, __func__, __LINE__, #expr, TRUE, FALSE);     \
         }                                                                    \
     } while(0)
 
 /*
  * Function return codes
  *
  * Most Pacemaker API functions return an integer return code. There are two
  * alternative interpretations. The legacy interpration is that the absolute
  * value of the return code is either a system error number or a custom
  * pcmk_err_* number. This is less than ideal because system error numbers are
  * constrained only to the positive int range, so there's the possibility that
  * system errors and custom errors could collide (which did in fact happen
  * already on one architecture). The new intepretation is that negative values
  * are from the pcmk_rc_e enum, and positive values are system error numbers.
  * Both use 0 for success.
  *
  * For system error codes, see:
  * - /usr/include/asm-generic/errno.h
  * - /usr/include/asm-generic/errno-base.h
  */
 
 // Legacy custom return codes for Pacemaker API functions (deprecated)
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define pcmk_ok                       0
+
 #  define PCMK_ERROR_OFFSET             190    /* Replacements on non-linux systems, see include/portability.h */
 #  define PCMK_CUSTOM_OFFSET            200    /* Purely custom codes */
 #  define pcmk_err_generic              201
 #  define pcmk_err_no_quorum            202
 #  define pcmk_err_schema_validation    203
 #  define pcmk_err_transform_failed     204
 #  define pcmk_err_old_data             205
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define pcmk_err_diff_failed          206
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 #  define pcmk_err_diff_resync          207
+
 #  define pcmk_err_cib_modified         208
 #  define pcmk_err_cib_backup           209
 #  define pcmk_err_cib_save             210
 #  define pcmk_err_schema_unchanged     211
 #  define pcmk_err_cib_corrupt          212
 #  define pcmk_err_multiple             213
 #  define pcmk_err_node_unknown         214
 #  define pcmk_err_already              215
 /* On HPPA 215 is ENOSYM (Unknown error 215), which hopefully never happens. */
 #ifdef __hppa__
 #  define pcmk_err_bad_nvpair           250 /* 216 is ENOTSOCK */
 #  define pcmk_err_unknown_format       252 /* 217 is EDESTADDRREQ */
 #else
 #  define pcmk_err_bad_nvpair           216
 #  define pcmk_err_unknown_format       217
 #endif
 
 /*!
  * \enum pcmk_rc_e
  * \brief Return codes for Pacemaker API functions
  *
  * Any Pacemaker API function documented as returning a "standard Pacemaker
  * return code" will return pcmk_rc_ok (0) on success, and one of this
  * enumeration's other (negative) values or a (positive) system error number
  * otherwise. The custom codes are at -1001 and lower, so that the caller may
  * use -1 through -1000 for their own custom values if desired. While generally
  * referred to as "errors", nonzero values simply indicate a result, which might
  * or might not be an error depending on the calling context.
  */
 enum pcmk_rc_e {
     /* When adding new values, use consecutively lower numbers, update the array
      * in lib/common/results.c, and test with crm_error.
      */
     pcmk_rc_compression         = -1039,
     pcmk_rc_ns_resolution       = -1038,
     pcmk_rc_no_transaction      = -1037,
     pcmk_rc_bad_xml_patch       = -1036,
     pcmk_rc_bad_input           = -1035,
     pcmk_rc_disabled            = -1034,
     pcmk_rc_duplicate_id        = -1033,
     pcmk_rc_unpack_error        = -1032,
     pcmk_rc_invalid_transition  = -1031,
     pcmk_rc_graph_error         = -1030,
     pcmk_rc_dot_error           = -1029,
     pcmk_rc_underflow           = -1028,
     pcmk_rc_no_input            = -1027,
     pcmk_rc_no_output           = -1026,
     pcmk_rc_after_range         = -1025,
     pcmk_rc_within_range        = -1024,
     pcmk_rc_before_range        = -1023,
     pcmk_rc_undetermined        = -1022,
     pcmk_rc_op_unsatisfied      = -1021,
     pcmk_rc_ipc_pid_only        = -1020,
     pcmk_rc_ipc_unresponsive    = -1019,
     pcmk_rc_ipc_unauthorized    = -1018,
     pcmk_rc_no_quorum           = -1017,
     pcmk_rc_schema_validation   = -1016,
     pcmk_rc_schema_unchanged    = -1015,
     pcmk_rc_transform_failed    = -1014,
     pcmk_rc_old_data            = -1013,
     pcmk_rc_diff_failed         = -1012,
     pcmk_rc_diff_resync         = -1011,
     pcmk_rc_cib_modified        = -1010,
     pcmk_rc_cib_backup          = -1009,
     pcmk_rc_cib_save            = -1008,
     pcmk_rc_cib_corrupt         = -1007,
     pcmk_rc_multiple            = -1006,
     pcmk_rc_node_unknown        = -1005,
     pcmk_rc_already             = -1004,
     pcmk_rc_bad_nvpair          = -1003,
     pcmk_rc_unknown_format      = -1002,
     // Developers: Use a more specific code than pcmk_rc_error whenever possible
     pcmk_rc_error               = -1001,
 
     // Values -1 through -1000 reserved for caller use
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     pcmk_rc_ok                  =     0
 
     // Positive values reserved for system error numbers
 };
 
 
 /*!
  * \enum ocf_exitcode
  * \brief Exit status codes for resource agents
  *
  * The OCF Resource Agent API standard enumerates the possible exit status codes
  * that agents should return. Besides being used with OCF agents, these values
  * are also used by the executor as a universal status for all agent standards;
  * actual results are mapped to these before returning them to clients.
  */
 enum ocf_exitcode {
     PCMK_OCF_OK                   = 0,   //!< Success
+
+    // NOTE: booth (as of at least 1.1) uses this value
     PCMK_OCF_UNKNOWN_ERROR        = 1,   //!< Unspecified error
+
     PCMK_OCF_INVALID_PARAM        = 2,   //!< Parameter invalid (in local context)
     PCMK_OCF_UNIMPLEMENT_FEATURE  = 3,   //!< Requested action not implemented
     PCMK_OCF_INSUFFICIENT_PRIV    = 4,   //!< Insufficient privileges
     PCMK_OCF_NOT_INSTALLED        = 5,   //!< Dependencies not available locally
     PCMK_OCF_NOT_CONFIGURED       = 6,   //!< Parameter invalid (inherently)
+
+    // NOTE: booth (as of at least 1.1) uses this value
     PCMK_OCF_NOT_RUNNING          = 7,   //!< Service safely stopped
+
     PCMK_OCF_RUNNING_PROMOTED     = 8,   //!< Service active and promoted
     PCMK_OCF_FAILED_PROMOTED      = 9,   //!< Service failed and possibly in promoted role
     PCMK_OCF_DEGRADED             = 190, //!< Service active but more likely to fail soon
     PCMK_OCF_DEGRADED_PROMOTED    = 191, //!< Service promoted but more likely to fail soon
 
     /* These two are Pacemaker extensions, not in the OCF standard. The
      * controller records PCMK_OCF_UNKNOWN for pending actions.
      * PCMK_OCF_CONNECTION_DIED is used only with older DCs that don't support
      * PCMK_EXEC_NOT_CONNECTED.
      */
     PCMK_OCF_CONNECTION_DIED      = 189, //!< \deprecated See PCMK_EXEC_NOT_CONNECTED
     PCMK_OCF_UNKNOWN              = 193, //!< Action is pending
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     // Former Pacemaker extensions
     PCMK_OCF_EXEC_ERROR           = 192, //!< \deprecated (Unused)
     PCMK_OCF_SIGNAL               = 194, //!< \deprecated (Unused)
     PCMK_OCF_NOT_SUPPORTED        = 195, //!< \deprecated (Unused)
     PCMK_OCF_PENDING              = 196, //!< \deprecated (Unused)
     PCMK_OCF_CANCELLED            = 197, //!< \deprecated (Unused)
     PCMK_OCF_TIMEOUT              = 198, //!< \deprecated (Unused)
     PCMK_OCF_OTHER_ERROR          = 199, //!< \deprecated (Unused)
 
     //! \deprecated Use PCMK_OCF_RUNNING_PROMOTED instead
     PCMK_OCF_RUNNING_MASTER     = PCMK_OCF_RUNNING_PROMOTED,
 
     //! \deprecated Use PCMK_OCF_FAILED_PROMOTED instead
     PCMK_OCF_FAILED_MASTER      = PCMK_OCF_FAILED_PROMOTED,
 
     //! \deprecated Use PCMK_OCF_DEGRADED_PROMOTED instead
     PCMK_OCF_DEGRADED_MASTER    = PCMK_OCF_DEGRADED_PROMOTED,
 #endif
 };
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /*!
  * \enum crm_exit_e
  * \brief Exit status codes for tools and daemons
  *
  * We want well-specified (i.e. OS-invariant) exit status codes for our daemons
  * and applications so they can be relied on by callers. (Function return codes
  * and errno's do not make good exit statuses.)
  *
  * The only hard rule is that exit statuses must be between 0 and 255; all else
  * is convention. Universally, 0 is success, and 1 is generic error (excluding
  * OSes we don't support -- for example, OpenVMS considers 1 success!).
  *
  * For init scripts, the LSB gives meaning to 0-7, and sets aside 150-199 for
  * application use. OCF adds 8-9 and 190-191.
  *
  * sysexits.h was an attempt to give additional meanings, but never really
  * caught on. It uses 0 and 64-78.
  *
  * Bash reserves 2 ("incorrect builtin usage") and 126-255 (126 is "command
  * found but not executable", 127 is "command not found", 128 + n is
  * "interrupted by signal n").
  *
  * tldp.org recommends 64-113 for application use.
  *
  * We try to overlap with the above conventions when practical.
  */
 typedef enum crm_exit_e {
     // Common convention
     CRM_EX_OK                   =   0, //!< Success
     CRM_EX_ERROR                =   1, //!< Unspecified error
 
     // LSB + OCF
     CRM_EX_INVALID_PARAM        =   2, //!< Parameter invalid (in local context)
     CRM_EX_UNIMPLEMENT_FEATURE  =   3, //!< Requested action not implemented
     CRM_EX_INSUFFICIENT_PRIV    =   4, //!< Insufficient privileges
     CRM_EX_NOT_INSTALLED        =   5, //!< Dependencies not available locally
     CRM_EX_NOT_CONFIGURED       =   6, //!< Parameter invalid (inherently)
     CRM_EX_NOT_RUNNING          =   7, //!< Service safely stopped
     CRM_EX_PROMOTED             =   8, //!< Service active and promoted
     CRM_EX_FAILED_PROMOTED      =   9, //!< Service failed and possibly promoted
 
     // sysexits.h
     CRM_EX_USAGE                =  64, //!< Command line usage error
     CRM_EX_DATAERR              =  65, //!< User-supplied data incorrect
     CRM_EX_NOINPUT              =  66, //!< Input file not available
     CRM_EX_NOUSER               =  67, //!< User does not exist
     CRM_EX_NOHOST               =  68, //!< Host unknown
     CRM_EX_UNAVAILABLE          =  69, //!< Needed service unavailable
     CRM_EX_SOFTWARE             =  70, //!< Internal software bug
     CRM_EX_OSERR                =  71, //!< External (OS/environmental) problem
     CRM_EX_OSFILE               =  72, //!< System file not usable
     CRM_EX_CANTCREAT            =  73, //!< File couldn't be created
     CRM_EX_IOERR                =  74, //!< File I/O error
     CRM_EX_TEMPFAIL             =  75, //!< Try again
     CRM_EX_PROTOCOL             =  76, //!< Protocol violated
     CRM_EX_NOPERM               =  77, //!< Non-file permission issue
     CRM_EX_CONFIG               =  78, //!< Misconfiguration
 
     // Custom
     CRM_EX_FATAL                = 100, //!< Do not respawn
     CRM_EX_PANIC                = 101, //!< Panic the local host
     CRM_EX_DISCONNECT           = 102, //!< Lost connection to something
     CRM_EX_OLD                  = 103, //!< Update older than existing config
     CRM_EX_DIGEST               = 104, //!< Digest comparison failed
     CRM_EX_NOSUCH               = 105, //!< Requested item does not exist
     CRM_EX_QUORUM               = 106, //!< Local partition does not have quorum
     CRM_EX_UNSAFE               = 107, //!< Requires --force or new conditions
     CRM_EX_EXISTS               = 108, //!< Requested item already exists
     CRM_EX_MULTIPLE             = 109, //!< Requested item has multiple matches
     CRM_EX_EXPIRED              = 110, //!< Requested item has expired
     CRM_EX_NOT_YET_IN_EFFECT    = 111, //!< Requested item is not in effect
     CRM_EX_INDETERMINATE        = 112, //!< Could not determine status
     CRM_EX_UNSATISFIED          = 113, //!< Requested item does not satisfy constraints
 
     // Other
     CRM_EX_TIMEOUT              = 124, //!< Convention from timeout(1)
 
     /* Anything above 128 overlaps with some shells' use of these values for
      * "interrupted by signal N", and so may be unreliable when detected by
      * shell scripts.
      */
 
     // OCF Resource Agent API 1.1
     CRM_EX_DEGRADED             = 190, //!< Service active but more likely to fail soon
     CRM_EX_DEGRADED_PROMOTED    = 191, //!< Service promoted but more likely to fail soon
 
     /* Custom
      *
      * This can be used to initialize exit status variables or to indicate that
      * a command is pending (which is what the controller uses it for).
      */
     CRM_EX_NONE                 = 193, //!< No exit status available
 
     CRM_EX_MAX                  = 255, //!< Ensure crm_exit_t can hold this
 } crm_exit_t;
 
 /*!
  * \enum pcmk_exec_status
  * \brief Execution status
  *
  * These codes are used to specify the result of the attempt to execute an
  * agent, rather than the agent's result itself.
  */
 enum pcmk_exec_status {
     PCMK_EXEC_UNKNOWN = -2,     //!< Used only to initialize variables
     PCMK_EXEC_PENDING = -1,     //!< Action is in progress
     PCMK_EXEC_DONE,             //!< Action completed, result is known
     PCMK_EXEC_CANCELLED,        //!< Action was cancelled
     PCMK_EXEC_TIMEOUT,          //!< Action did not complete in time
     PCMK_EXEC_NOT_SUPPORTED,    //!< Agent does not implement requested action
     PCMK_EXEC_ERROR,            //!< Execution failed, may be retried
     PCMK_EXEC_ERROR_HARD,       //!< Execution failed, do not retry on node
     PCMK_EXEC_ERROR_FATAL,      //!< Execution failed, do not retry anywhere
     PCMK_EXEC_NOT_INSTALLED,    //!< Agent or dependency not available locally
     PCMK_EXEC_NOT_CONNECTED,    //!< No connection to executor
     PCMK_EXEC_INVALID,          //!< Action cannot be attempted (e.g. shutdown)
     PCMK_EXEC_NO_FENCE_DEVICE,  //!< No fence device is configured for target
     PCMK_EXEC_NO_SECRETS,       //!< Necessary CIB secrets are unavailable
 
     // Add new values above here then update this one below
     PCMK_EXEC_MAX = PCMK_EXEC_NO_SECRETS, //!< Maximum value for this enum
 };
 
 /*!
  * \enum pcmk_result_type
  * \brief Types of Pacemaker result codes
  *
  * A particular integer can have different meanings within different Pacemaker
  * result code families. It may be interpretable within zero, one, or multiple
  * families.
  *
  * These values are useful for specifying how an integer result code should be
  * interpreted in situations involving a generic integer value. For example, a
  * function that can process multiple types of result codes might accept an
  * arbitrary integer argument along with a \p pcmk_result_type argument that
  * specifies how to interpret the integer.
  */
 enum pcmk_result_type {
     pcmk_result_legacy      = 0,  //!< Legacy API function return code
     pcmk_result_rc          = 1,  //!< Standard Pacemaker return code
     pcmk_result_exitcode    = 2,  //!< Exit status code
     pcmk_result_exec_status = 3,  //!< Execution status
 };
 
 int pcmk_result_get_strings(int code, enum pcmk_result_type type,
                             const char **name, const char **desc);
 const char *pcmk_rc_name(int rc);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 const char *pcmk_rc_str(int rc);
+
 crm_exit_t pcmk_rc2exitc(int rc);
 enum ocf_exitcode pcmk_rc2ocf(int rc);
 int pcmk_rc2legacy(int rc);
 int pcmk_legacy2rc(int legacy_rc);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 const char *pcmk_strerror(int rc);
+
 const char *pcmk_errorname(int rc);
 const char *crm_exit_name(crm_exit_t exit_code);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 const char *crm_exit_str(crm_exit_t exit_code);
+
 _Noreturn crm_exit_t crm_exit(crm_exit_t rc);
 
 static inline const char *
 pcmk_exec_status_str(enum pcmk_exec_status status)
 {
     switch (status) {
         case PCMK_EXEC_PENDING:         return "pending";
         case PCMK_EXEC_DONE:            return "complete";
         case PCMK_EXEC_CANCELLED:       return "Cancelled";
         case PCMK_EXEC_TIMEOUT:         return "Timed Out";
         case PCMK_EXEC_NOT_SUPPORTED:   return "NOT SUPPORTED";
         case PCMK_EXEC_ERROR:           return "Error";
         case PCMK_EXEC_ERROR_HARD:      return "Hard error";
         case PCMK_EXEC_ERROR_FATAL:     return "Fatal error";
         case PCMK_EXEC_NOT_INSTALLED:   return "Not installed";
         case PCMK_EXEC_NOT_CONNECTED:   return "Internal communication failure";
         case PCMK_EXEC_INVALID:         return "Cannot execute now";
         case PCMK_EXEC_NO_FENCE_DEVICE: return "No fence device";
         case PCMK_EXEC_NO_SECRETS:      return "CIB secrets unavailable";
         default:                        return "UNKNOWN!";
     }
 }
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/scheduler.h b/include/crm/common/scheduler.h
index 63d8095df2..27e12d6aa0 100644
--- a/include/crm/common/scheduler.h
+++ b/include/crm/common/scheduler.h
@@ -1,273 +1,288 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_SCHEDULER__H
 #  define PCMK__CRM_COMMON_SCHEDULER__H
 
 #include <sys/types.h>                  // time_t
 #include <libxml/tree.h>                // xmlNode
 #include <glib.h>                       // guint, GList, GHashTable
 
 #include <crm/common/iso8601.h>         // crm_time_t
 
 #include <crm/common/actions.h>
 #include <crm/common/nodes.h>
 #include <crm/common/resources.h>
 #include <crm/common/roles.h>
 #include <crm/common/rules.h>
 #include <crm/common/scheduler_types.h>
 #include <crm/common/tags.h>
 #include <crm/common/tickets.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*!
  * \file
  * \brief Scheduler API
  * \ingroup core
  */
 
+// NOTE: sbd (as of at least 1.5.2) uses this enum
 //! Possible responses to loss of quorum
 enum pe_quorum_policy {
     pcmk_no_quorum_freeze,  //<! Do not recover resources from outside partition
     pcmk_no_quorum_stop,    //<! Stop all resources in partition
     pcmk_no_quorum_ignore,  //<! Act as if partition still holds quorum
     pcmk_no_quorum_fence,   //<! Fence all nodes in partition
     pcmk_no_quorum_demote,  //<! Demote promotable resources and stop all others
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     //! \deprecated Use pcmk_no_quorum_freeze instead
     no_quorum_freeze    = pcmk_no_quorum_freeze,
 
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     //! \deprecated Use pcmk_no_quorum_stop instead
     no_quorum_stop      = pcmk_no_quorum_stop,
 
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     //! \deprecated Use pcmk_no_quorum_ignore instead
     no_quorum_ignore    = pcmk_no_quorum_ignore,
 
     //! \deprecated Use pcmk_no_quorum_fence instead
     no_quorum_suicide   = pcmk_no_quorum_fence,
 
+    // NOTE: sbd (as of at least 1.5.2) uses this value
     //! \deprecated Use pcmk_no_quorum_demote instead
     no_quorum_demote    = pcmk_no_quorum_demote,
 #endif
 };
 
 //! Scheduling options and conditions
 enum pcmk_scheduler_flags {
     //! No scheduler flags set (compare with equality rather than bit set)
     pcmk_sched_none                     = 0ULL,
 
     // These flags are dynamically determined conditions
 
     //! Whether partition has quorum (via \c PCMK_XA_HAVE_QUORUM attribute)
     pcmk_sched_quorate                  = (1ULL << 0),
 
     //! Whether cluster is symmetric (via symmetric-cluster property)
     pcmk_sched_symmetric_cluster        = (1ULL << 1),
 
     //! Whether cluster is in maintenance mode (via maintenance-mode property)
     pcmk_sched_in_maintenance           = (1ULL << 3),
 
     //! Whether fencing is enabled (via stonith-enabled property)
     pcmk_sched_fencing_enabled          = (1ULL << 4),
 
     //! Whether cluster has a fencing resource (via CIB resources)
     pcmk_sched_have_fencing             = (1ULL << 5),
 
     //! Whether any resource provides or requires unfencing (via CIB resources)
     pcmk_sched_enable_unfencing         = (1ULL << 6),
 
     //! Whether concurrent fencing is allowed (via concurrent-fencing property)
     pcmk_sched_concurrent_fencing       = (1ULL << 7),
 
     /*!
      * Whether resources removed from the configuration should be stopped (via
      * stop-orphan-resources property)
      */
     pcmk_sched_stop_removed_resources   = (1ULL << 8),
 
     /*!
      * Whether recurring actions removed from the configuration should be
      * cancelled (via stop-orphan-actions property)
      */
     pcmk_sched_cancel_removed_actions   = (1ULL << 9),
 
     //! Whether to stop all resources (via stop-all-resources property)
     pcmk_sched_stop_all                 = (1ULL << 10),
 
     /*!
      * Whether start failure should be treated as if
      * \c PCMK_META_MIGRATION_THRESHOLD is 1 (via
      * \c PCMK_OPT_START_FAILURE_IS_FATAL property)
      */
     pcmk_sched_start_failure_fatal      = (1ULL << 12),
 
     //! \deprecated Do not use
     pcmk_sched_remove_after_stop        = (1ULL << 13),
 
     //! Whether unseen nodes should be fenced (via startup-fencing property)
     pcmk_sched_startup_fencing          = (1ULL << 14),
 
     /*!
      * Whether resources should be left stopped when their node shuts down
      * cleanly (via shutdown-lock property)
      */
     pcmk_sched_shutdown_lock            = (1ULL << 15),
 
     /*!
      * Whether resources' current state should be probed (when unknown) before
      * scheduling any other actions (via the enable-startup-probes property)
      */
     pcmk_sched_probe_resources          = (1ULL << 16),
 
     //! Whether the CIB status section has been parsed yet
     pcmk_sched_have_status              = (1ULL << 17),
 
     //! Whether the cluster includes any Pacemaker Remote nodes (via CIB)
     pcmk_sched_have_remote_nodes        = (1ULL << 18),
 
     // The remaining flags are scheduling options that must be set explicitly
 
     /*!
      * Whether to skip unpacking the CIB status section and stop the scheduling
      * sequence after applying node-specific location criteria (skipping
      * assignment, ordering, actions, etc.).
      */
     pcmk_sched_location_only            = (1ULL << 20),
 
     //! Whether sensitive resource attributes have been masked
     pcmk_sched_sanitized                = (1ULL << 21),
 
     //! Skip counting of total, disabled, and blocked resource instances
     pcmk_sched_no_counts                = (1ULL << 23),
 
     /*!
      * Skip deprecated code kept solely for backward API compatibility
      * (internal code should always set this)
      */
     pcmk_sched_no_compat                = (1ULL << 24),
 
     //! Whether node scores should be output instead of logged
     pcmk_sched_output_scores            = (1ULL << 25),
 
     //! Whether to show node and resource utilization (in log or output)
     pcmk_sched_show_utilization         = (1ULL << 26),
 
     /*!
      * Whether to stop the scheduling sequence after unpacking the CIB,
      * calculating cluster status, and applying node health (skipping
      * applying node-specific location criteria, assignment, etc.)
      */
     pcmk_sched_validate_only            = (1ULL << 27),
 };
 
 // Implementation of pcmk_scheduler_t
 // @COMPAT Make contents internal when we can break API backward compatibility
 //!@{
 //! \deprecated Do not use (public access will be removed in a future release)
 struct pe_working_set_s {
     // Be careful about when each piece of information is available and final
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated To set scheduler iput, use pcmk_set_scheduler_cib() instead
     xmlNode *input;                 // CIB XML
 
     crm_time_t *now;                // Current time for evaluation purposes
     char *dc_uuid;                  // Node ID of designated controller
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     //! \deprecated Call pcmk_get_dc() instead
     pcmk_node_t *dc_node;           // Node object for DC
 
     const char *stonith_action;     // Default fencing action
     const char *placement_strategy; // Value of placement-strategy property
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
     // @COMPAT Change to uint64_t at a compatibility break
-    //! \deprecated Call pcmk_get_no_quorum_policy() to get no-quorum policy
+    //! \deprecated Call pcmk_has_quorum() to check quorum
     unsigned long long flags;       // Group of enum pcmk_scheduler_flags
 
     int stonith_timeout;            // Value of stonith-timeout property
+
+    // NOTE: sbd (as of at least 1.5.2) uses this
+    //! \deprecated Call pcmk_get_no_quorum_policy() to get no-quorum policy
     enum pe_quorum_policy no_quorum_policy; // Response to loss of quorum
+
     GHashTable *config_hash;        // Cluster properties
 
     // Ticket constraints unpacked from ticket state
     GHashTable *tickets;
 
     // Actions for which there can be only one (such as "fence node X")
     GHashTable *singletons;
 
+    // NOTE: sbd (as of at least 1.5.2) uses this
+    //! \deprecated Call pcmk_find_node() to find a node instead
     GList *nodes;                   // Nodes in cluster
+
     GList *resources;               // Resources in cluster
     GList *placement_constraints;   // Location constraints
     GList *ordering_constraints;    // Ordering constraints
     GList *colocation_constraints;  // Colocation constraints
 
     // Ticket constraints unpacked by libpacemaker
     GList *ticket_constraints;
 
     GList *actions;                 // Scheduled actions
     xmlNode *failed;                // History entries of failed actions
     xmlNode *op_defaults;           // Configured operation defaults
     xmlNode *rsc_defaults;          // Configured resource defaults
     int num_synapse;                // Number of transition graph synapses
     int max_valid_nodes;            // \deprecated Do not use
     int order_id;                   // ID to use for next created ordering
     int action_id;                  // ID to use for next created action
     xmlNode *graph;                 // Transition graph
     GHashTable *template_rsc_sets;  // Mappings of template ID to resource ID
 
     // @COMPAT Replace this with a fencer variable (only place it's used)
     const char *localhost;          // \deprecated Do not use
 
     GHashTable *tags;               // Configuration tags (ID -> pcmk_tag_t *)
     int blocked_resources;          // Number of blocked resources in cluster
     int disabled_resources;         // Number of disabled resources in cluster
     GList *param_check;             // History entries that need to be checked
     GList *stop_needed;             // Containers that need stop actions
     time_t recheck_by;              // Hint to controller when to reschedule
     int ninstances;                 // Total number of resource instances
     guint shutdown_lock;            // How long to lock resources (seconds)
     int priority_fencing_delay;     // Priority fencing delay
 
     // pcmk__output_t *
     void *priv;                     // For Pacemaker use only
 
     guint node_pending_timeout;     // Pending join times out after this (ms)
 };
 //!@}
 
 /* Whether the scheduler input currently being processed has warnings or errors
  *
  * @COMPAT When we can break API compatibility, we should make these
  * internal-only. Ideally they would be converted to pcmk_scheduler_flags
  * values, but everywhere they're needed doesn't currently have access to the
  * scheduler data.
  */
 //!@{
 //! \deprecated Do not use
 extern gboolean was_processing_error;
 extern gboolean was_processing_warning;
 //!@}
 
 pcmk_node_t *pcmk_get_dc(const pcmk_scheduler_t *scheduler);
 enum pe_quorum_policy pcmk_get_no_quorum_policy(const pcmk_scheduler_t
                                                 *scheduler);
 
 int pcmk_set_scheduler_cib(pcmk_scheduler_t *scheduler, xmlNode *cib);
 
 bool pcmk_has_quorum(const pcmk_scheduler_t *scheduler);
 pcmk_node_t *pcmk_find_node(const pcmk_scheduler_t *scheduler,
                             const char *node_name);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_SCHEDULER__H
diff --git a/include/crm/common/util.h b/include/crm/common/util.h
index c9ee41b3a8..bc3024cfd3 100644
--- a/include/crm/common/util.h
+++ b/include/crm/common/util.h
@@ -1,119 +1,127 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_UTIL__H
 #  define PCMK__CRM_COMMON_UTIL__H
 
 #  include <sys/types.h>    // gid_t, mode_t, size_t, time_t, uid_t
 #  include <stdlib.h>
 #  include <stdbool.h>
 #  include <stdint.h>       // uint32_t
 #  include <limits.h>
 #  include <signal.h>
 #  include <glib.h>
 
 #  include <crm/common/acl.h>
 #  include <crm/common/actions.h>
 #  include <crm/common/agents.h>
 #  include <crm/common/results.h>
 #  include <crm/common/scores.h>
 #  include <crm/common/nvpair.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Utility functions
  * \ingroup core
  */
 
 /* public node attribute functions (from attrd_client.c) */
 char *pcmk_promotion_score_name(const char *rsc_id);
 
 /* public Pacemaker Remote functions (from remote.c) */
 int crm_default_remote_port(void);
 
 /* public string functions (from strings.c) */
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 gboolean crm_is_true(const char *s);
+
 int crm_str_to_boolean(const char *s, int *ret);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 long long crm_get_msec(const char *input);
+
 char * crm_strip_trailing_newline(char *str);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 char *crm_strdup_printf(char const *format, ...) G_GNUC_PRINTF(1, 2);
 
 int pcmk_parse_interval_spec(const char *input, guint *result_ms);
 
 int compare_version(const char *version1, const char *version2);
 
 /* coverity[+kill] */
 void crm_abort(const char *file, const char *function, int line,
                const char *condition, gboolean do_core, gboolean do_fork);
 
 /*!
  * \brief Check whether any of specified flags are set in a flag group
  *
  * \param[in] flag_group        The flag group being examined
  * \param[in] flags_to_check    Which flags in flag_group should be checked
  *
  * \return true if \p flags_to_check is nonzero and any of its flags are set in
  *         \p flag_group, or false otherwise
  */
 static inline bool
 pcmk_any_flags_set(uint64_t flag_group, uint64_t flags_to_check)
 {
     return (flag_group & flags_to_check) != 0;
 }
 
 /*!
  * \brief Check whether all of specified flags are set in a flag group
  *
  * \param[in] flag_group        The flag group being examined
  * \param[in] flags_to_check    Which flags in flag_group should be checked
  *
  * \return true if \p flags_to_check is zero or all of its flags are set in
  *         \p flag_group, or false otherwise
  */
 static inline bool
 pcmk_all_flags_set(uint64_t flag_group, uint64_t flags_to_check)
 {
     return (flag_group & flags_to_check) == flags_to_check;
 }
 
 /*!
  * \brief Convenience alias for pcmk_all_flags_set(), to check single flag
  */
 #define pcmk_is_set(g, f)   pcmk_all_flags_set((g), (f))
 
 char *crm_md5sum(const char *buffer);
 
 char *crm_generate_uuid(void);
 
 // This belongs in ipc.h but is here for backward compatibility
 bool crm_is_daemon_name(const char *name);
 
 int crm_user_lookup(const char *name, uid_t * uid, gid_t * gid);
 int pcmk_daemon_user(uid_t *uid, gid_t *gid);
 
 #ifdef HAVE_GNUTLS_GNUTLS_H
 void crm_gnutls_global_init(void);
 #endif
 
 bool pcmk_str_is_infinity(const char *s);
 bool pcmk_str_is_minus_infinity(const char *s);
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/common/util_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/util_compat.h b/include/crm/common/util_compat.h
index 68db908b89..5a1d56a79c 100644
--- a/include/crm/common/util_compat.h
+++ b/include/crm/common/util_compat.h
@@ -1,177 +1,178 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_UTIL_COMPAT__H
 #  define PCMK__CRM_COMMON_UTIL_COMPAT__H
 
 #  include <glib.h>
 #  include <libxml/tree.h>
 #  include <crm/common/util.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker utilities
  * \ingroup core
  * \deprecated Do not include this header directly. The utilities in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Do not use
 #define crm_get_interval crm_parse_interval_spec
 
 //! \deprecated Do not use
 #define CRM_DEFAULT_OP_TIMEOUT_S "20s"
 
 //! \deprecated Use !pcmk_is_set() or !pcmk_all_flags_set() instead
 static inline gboolean
 is_not_set(long long word, long long bit)
 {
     return ((word & bit) == 0);
 }
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_is_set() or pcmk_all_flags_set() instead
 static inline gboolean
 is_set(long long word, long long bit)
 {
     return ((word & bit) == bit);
 }
 
 //! \deprecated Use pcmk_any_flags_set() instead
 static inline gboolean
 is_set_any(long long word, long long bit)
 {
     return ((word & bit) != 0);
 }
 
 //! \deprecated Use strcmp() or strcasecmp() instead
 gboolean crm_str_eq(const char *a, const char *b, gboolean use_case);
 
 //! \deprecated Use strcmp() instead
 gboolean safe_str_neq(const char *a, const char *b);
 
 //! \deprecated Use strcasecmp() instead
 #define safe_str_eq(a, b) crm_str_eq(a, b, FALSE)
 
 //! \deprecated Use snprintf() instead
 char *crm_itoa_stack(int an_int, char *buf, size_t len);
 
 //! \deprecated Use sscanf() instead
 int pcmk_scan_nvpair(const char *input, char **name, char **value);
 
 //! \deprecated Use a standard printf()-style function instead
 char *pcmk_format_nvpair(const char *name, const char *value,
                          const char *units);
 
 //! \deprecated Use \c crm_xml_add() or \c xml_remove_prop() instead
 const char *crm_xml_replace(xmlNode *node, const char *name, const char *value);
 
 //! \deprecated Use a standard printf()-style function instead
 char *pcmk_format_named_time(const char *name, time_t epoch_time);
 
 //! \deprecated Use strtoll() instead
 long long crm_parse_ll(const char *text, const char *default_text);
 
 //! \deprecated Use strtoll() instead
 int crm_parse_int(const char *text, const char *default_text);
 
 //! \deprecated Use strtoll() instead
 #  define crm_atoi(text, default_text) crm_parse_int(text, default_text)
 
 //! \deprecated Use g_str_hash() instead
 guint g_str_hash_traditional(gconstpointer v);
 
 //! \deprecated Use g_str_hash() instead
 #define crm_str_hash g_str_hash_traditional
 
 //! \deprecated Do not use Pacemaker for generic string comparison
 gboolean crm_strcase_equal(gconstpointer a, gconstpointer b);
 
 //! \deprecated Do not use Pacemaker for generic string manipulation
 guint crm_strcase_hash(gconstpointer v);
 
 //! \deprecated Use g_hash_table_new_full() instead
 static inline GHashTable *
 crm_str_table_new(void)
 {
     return g_hash_table_new_full(crm_str_hash, g_str_equal, free, free);
 }
 
 //! \deprecated Use g_hash_table_new_full() instead
 static inline GHashTable *
 crm_strcase_table_new(void)
 {
     return g_hash_table_new_full(crm_strcase_hash, crm_strcase_equal,
                                  free, free);
 }
 
 //! \deprecated Do not use Pacemaker for generic hash table manipulation
 GHashTable *crm_str_table_dup(GHashTable *old_table);
 
 //! \deprecated Use g_hash_able_size() instead
 static inline guint
 crm_hash_table_size(GHashTable *hashtable)
 {
     if (hashtable == NULL) {
         return 0;
     }
     return g_hash_table_size(hashtable);
 }
 
 //! \deprecated Don't use Pacemaker for string manipulation
 char *crm_strip_trailing_newline(char *str);
 
 //! \deprecated Don't use Pacemaker for string manipulation
 int pcmk_numeric_strcasecmp(const char *s1, const char *s2);
 
 //! \deprecated Don't use Pacemaker for string manipulation
 static inline char *
 crm_itoa(int an_int)
 {
     return crm_strdup_printf("%d", an_int);
 }
 
 //! \deprecated Don't use Pacemaker for string manipulation
 static inline char *
 crm_ftoa(double a_float)
 {
     return crm_strdup_printf("%f", a_float);
 }
 
 //! \deprecated Don't use Pacemaker for string manipulation
 static inline char *
 crm_ttoa(time_t epoch_time)
 {
     return crm_strdup_printf("%lld", (long long) epoch_time);
 }
 
 //! \deprecated Do not use Pacemaker libraries for generic I/O
 void crm_build_path(const char *path_c, mode_t mode);
 
 //! \deprecated Use \c pcmk_parse_interval_spec() instead
 guint crm_parse_interval_spec(const char *input);
 
 //! \deprecated Use \c PCMK_VALUE_ONLINE instead
 #define ONLINESTATUS PCMK_VALUE_ONLINE
 
 //! \deprecated Use \c PCMK_VALUE_OFFLINE instead
 #define OFFLINESTATUS PCMK_VALUE_OFFLINE
 
 //! \deprecated Use \c uname() instead
 char *pcmk_hostname(void);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_UTIL_COMPAT__H
diff --git a/include/crm/common/xml.h b/include/crm/common/xml.h
index d9fe40a649..53714b80a0 100644
--- a/include/crm/common/xml.h
+++ b/include/crm/common/xml.h
@@ -1,107 +1,113 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_XML__H
 #  define PCMK__CRM_COMMON_XML__H
 
 
 #  include <stdio.h>
 #  include <sys/types.h>
 #  include <unistd.h>
 
 #  include <stdlib.h>
 #  include <errno.h>
 #  include <fcntl.h>
 
 #  include <libxml/tree.h>
 #  include <libxml/xpath.h>
 
 #  include <crm/crm.h>
 #  include <crm/common/nvpair.h>
 #  include <crm/common/xml_io.h>
 #  include <crm/common/xml_names.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Wrappers for and extensions to libxml2
  * \ingroup core
  */
 
 typedef const xmlChar *pcmkXmlStr;
 
 
 /*
  * Searching & Modifying
  */
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level);
 
 char *calculate_on_disk_digest(xmlNode * local_cib);
 char *calculate_operation_digest(xmlNode * local_cib, const char *version);
 char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter,
                                      const char *version);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /*!
  * \brief Initialize the CRM XML subsystem
  *
  * This method sets global XML settings and loads pacemaker schemas into the cache.
  */
 void crm_xml_init(void);
+
 void crm_xml_cleanup(void);
 
 void pcmk_free_xml_subtree(xmlNode *xml);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 void free_xml(xmlNode * child);
 
 xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive);
 xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path);
 void crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
                               void (*helper)(xmlNode*, void*), void *user_data);
 xmlNode *expand_idref(xmlNode * input, xmlNode * top);
 
 void freeXpathObject(xmlXPathObjectPtr xpathObj);
 xmlNode *getXpathResult(xmlXPathObjectPtr xpathObj, int index);
 void dedupXpathResults(xmlXPathObjectPtr xpathObj);
 
 static inline int numXpathResults(xmlXPathObjectPtr xpathObj)
 {
     if(xpathObj == NULL || xpathObj->nodesetval == NULL) {
         return 0;
     }
     return xpathObj->nodesetval->nodeNr;
 }
 
 bool xml_tracking_changes(xmlNode * xml);
 bool xml_document_dirty(xmlNode *xml);
 void xml_track_changes(xmlNode * xml, const char *user, xmlNode *acl_source, bool enforce_acls);
 void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml);
 void xml_calculate_significant_changes(xmlNode *old_xml, xmlNode *new_xml);
 void xml_accept_changes(xmlNode * xml);
 bool xml_patch_versions(const xmlNode *patchset, int add[3], int del[3]);
 
 xmlNode *xml_create_patchset(
     int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version);
 int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version);
 
 void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest);
 
 void crm_xml_sanitize_id(char *id);
 void crm_xml_set_id(xmlNode *xml, const char *format, ...) G_GNUC_PRINTF(2, 3);
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/common/xml_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/common/xml_compat.h b/include/crm/common/xml_compat.h
index f47f5c3a9a..960169ba80 100644
--- a/include/crm/common/xml_compat.h
+++ b/include/crm/common/xml_compat.h
@@ -1,196 +1,199 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_COMMON_XML_COMPAT__H
 #  define PCMK__CRM_COMMON_XML_COMPAT__H
 
 #include <glib.h>               // gboolean
 #include <libxml/tree.h>        // xmlNode
 
 #include <crm/common/nvpair.h>  // crm_xml_add()
 #include <crm/common/xml_names.h>   // PCMK_XE_CLONE
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker XML API
  * \ingroup core
  * \deprecated Do not include this header directly. The XML APIs in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_PARANOIA_CHECKS 0
 
 //! \deprecated This function will be removed in a future release
 xmlDoc *getDocPtr(xmlNode *node);
 
 //! \deprecated This function will be removed in a future release
 int add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child);
 
 //! \deprecated This function will be removed in a future release
 xmlNode *find_entity(xmlNode *parent, const char *node_name, const char *id);
 
 //! \deprecated This function will be removed in a future release
 char *xml_get_path(const xmlNode *xml);
 
 //! \deprecated This function will be removed in a future release
 void xml_log_changes(uint8_t level, const char *function, const xmlNode *xml);
 
 //! \deprecated This function will be removed in a future release
 void xml_log_patchset(uint8_t level, const char *function, const xmlNode *xml);
 
 //!  \deprecated Use xml_apply_patchset() instead
 gboolean apply_xml_diff(xmlNode *old_xml, xmlNode *diff, xmlNode **new_xml);
 
 //! \deprecated Do not use (will be removed in a future release)
 void crm_destroy_xml(gpointer data);
 
 //! \deprecated Check children member directly
 gboolean xml_has_children(const xmlNode *root);
 
 //! \deprecated Use crm_xml_add() with "true" or "false" instead
 static inline const char *
 crm_xml_add_boolean(xmlNode *node, const char *name, gboolean value)
 {
     return crm_xml_add(node, name, (value? "true" : "false"));
 }
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use name member directly
 static inline const char *
 crm_element_name(const xmlNode *xml)
 {
     return (xml == NULL)? NULL : (const char *) xml->name;
 }
 
 //! \deprecated Do not use
 char *crm_xml_escape(const char *text);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *copy_xml(xmlNode *src_node);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *add_node_copy(xmlNode *new_parent, xmlNode *xml_node);
 
 //! \deprecated Do not use
 void purge_diff_markers(xmlNode *a_node);
 
 //! \deprecated Do not use
 xmlNode *diff_xml_object(xmlNode *left, xmlNode *right, gboolean suppress);
 
 //! \deprecated Do not use
 xmlNode *subtract_xml_object(xmlNode *parent, xmlNode *left, xmlNode *right,
                              gboolean full, gboolean *changed,
                              const char *marker);
 
 //! \deprecated Do not use
 gboolean can_prune_leaf(xmlNode *xml_node);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *create_xml_node(xmlNode *parent, const char *name);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *pcmk_create_xml_text_node(xmlNode *parent, const char *name,
                                    const char *content);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *pcmk_create_html_node(xmlNode *parent, const char *element_name,
                                const char *id, const char *class_name,
                                const char *text);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *first_named_child(const xmlNode *parent, const char *name);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *find_xml_node(const xmlNode *root, const char *search_path,
                        gboolean must_find);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *crm_next_same_xml(const xmlNode *sibling);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 void xml_remove_prop(xmlNode *obj, const char *name);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 gboolean replace_xml_child(xmlNode *parent, xmlNode *child, xmlNode *update,
                            gboolean delete_only);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 gboolean update_xml_child(xmlNode *child, xmlNode *to_update);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 int find_xml_children(xmlNode **children, xmlNode *root, const char *tag,
                       const char *field, const char *value,
                       gboolean search_matches);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *get_xpath_object_relative(const char *xpath, xmlNode *xml_obj,
                                    int error_level);
 
 //! \deprecated Do not use
 void fix_plus_plus_recursive(xmlNode *target);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml);
 
 //! \deprecated Do not use Pacemaker for general-purpose XML manipulation
 xmlNode *get_message_xml(const xmlNode *msg, const char *field);
 
 //! \deprecated Do not use
 const char *xml_latest_schema(void);
 
 //! \deprecated Do not use
 const char *get_schema_name(int version);
 
 //! \deprecated Do not use
 int get_schema_version(const char *name);
 
 //! \deprecated Do not use
 int update_validation(xmlNode **xml_blob, int *best, int max,
                       gboolean transform, gboolean to_logs);
 
 //! \deprecated Do not use
 gboolean validate_xml(xmlNode *xml_blob, const char *validation,
                       gboolean to_logs);
 
 //! \deprecated Do not use
 gboolean validate_xml_verbose(const xmlNode *xml_blob);
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Do not use
 gboolean cli_config_update(xmlNode **xml, int *best_version, gboolean to_logs);
 
 //! \deprecated Do not use
 static inline const char *
 crm_map_element_name(const xmlNode *xml)
 {
     if (xml == NULL) {
         return NULL;
     } else if (strcmp((const char *) xml->name, "master") == 0) {
         // Can't use PCMK__XE_PROMOTABLE_LEGACY because it's internal
         return PCMK_XE_CLONE;
     } else {
         return (const char *) xml->name;
     }
 }
 
 //! \deprecated Do not use
 void copy_in_properties(xmlNode *target, const xmlNode *src);
 
 //! \deprecated Do not use
 void expand_plus_plus(xmlNode * target, const char *name, const char *value);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_COMMON_XML_COMPAT__H
diff --git a/include/crm/crm.h b/include/crm/crm.h
index 7a120b92ac..2ef84d3fd8 100644
--- a/include/crm/crm.h
+++ b/include/crm/crm.h
@@ -1,160 +1,161 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CRM__H
 #  define PCMK__CRM_CRM__H
 
 #  include <crm_config.h>
 #  include <stdlib.h>
 #  include <glib.h>
 #  include <stdbool.h>
 
 #  include <string.h>
 
 #  include <libxml/tree.h>
 
 #include <crm/common/options.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief A dumping ground
  * \ingroup core
  */
 
 #ifndef PCMK_ALLOW_DEPRECATED
 /*!
  * \brief Allow use of deprecated Pacemaker APIs
  *
  * By default, external code using Pacemaker headers is allowed to use
  * deprecated Pacemaker APIs. If PCMK_ALLOW_DEPRECATED is defined to 0 before
  * including any Pacemaker headers, deprecated APIs will be unusable. It is
  * strongly recommended to leave this unchanged for production and release
  * builds, to avoid breakage when users upgrade to new Pacemaker releases that
  * deprecate more APIs. This should be defined to 0 only for development and
  * testing builds when desiring to check for usage of currently deprecated APIs.
  */
 #define PCMK_ALLOW_DEPRECATED 1
 #endif
 
 /*!
  * The CRM feature set assists with compatibility in mixed-version clusters.
  * The major version number increases when nodes with different versions
  * would not work (rolling upgrades are not allowed). The minor version
  * number increases when mixed-version clusters are allowed only during
  * rolling upgrades (a node with the oldest feature set will be elected DC). The
  * minor-minor version number is ignored, but allows resource agents to detect
  * cluster support for various features.
  *
  * The feature set also affects the processing of old saved CIBs (such as for
  * many scheduler regression tests).
  *
  * Particular feature points currently tested by Pacemaker code:
  *
  * >2.1:     Operation updates include timing data
  * >=3.0.5:  XML v2 digests are created
  * >=3.0.8:  Peers do not need acks for cancellations
  * >=3.0.9:  DC will send its own shutdown request to all peers
  *           XML v2 patchsets are created by default
  * >=3.0.13: Fail counts include operation name and interval
  * >=3.2.0:  DC supports PCMK_EXEC_INVALID and PCMK_EXEC_NOT_CONNECTED
  * >=3.19.0: DC supports PCMK__CIB_REQUEST_COMMIT_TRANSACT
  */
 #  define CRM_FEATURE_SET		"3.19.5"
 
 /* Pacemaker's CPG protocols use fixed-width binary fields for the sender and
  * recipient of a CPG message. This imposes an arbitrary limit on cluster node
  * names.
  */
 //! \brief Maximum length of a Corosync cluster node name (in bytes)
 #define MAX_NAME	256
 
 #  define CRM_META			"CRM_meta"
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 extern char *crm_system_name;
 
 /* Sub-systems */
 #  define CRM_SYSTEM_DC		"dc"
 #define CRM_SYSTEM_DCIB         "dcib" // Primary instance of CIB manager
 #  define CRM_SYSTEM_CIB		"cib"
 #  define CRM_SYSTEM_CRMD		"crmd"
 #  define CRM_SYSTEM_LRMD		"lrmd"
 #  define CRM_SYSTEM_PENGINE	"pengine"
 #  define CRM_SYSTEM_TENGINE	"tengine"
 #  define CRM_SYSTEM_STONITHD	"stonithd"
 #  define CRM_SYSTEM_MCP	"pacemakerd"
 
 // Names of internally generated node attributes
 // @TODO Replace these with PCMK_NODE_ATTR_*
 #  define CRM_ATTR_UNAME            "#uname"
 #  define CRM_ATTR_ID               "#id"
 #  define CRM_ATTR_KIND             "#kind"
 #  define CRM_ATTR_ROLE             "#role"
 #  define CRM_ATTR_IS_DC            "#is_dc"
 #  define CRM_ATTR_CLUSTER_NAME     "#cluster-name"
 #  define CRM_ATTR_SITE_NAME        "#site-name"
 #  define CRM_ATTR_UNFENCED         "#node-unfenced"
 #  define CRM_ATTR_DIGESTS_ALL      "#digests-all"
 #  define CRM_ATTR_DIGESTS_SECURE   "#digests-secure"
 #  define CRM_ATTR_PROTOCOL         "#attrd-protocol"
 #  define CRM_ATTR_FEATURE_SET      "#feature-set"
 
 /* Valid operations */
 #  define CRM_OP_NOOP		"noop"
 #  define CRM_OP_JOIN_ANNOUNCE	"join_announce"
 #  define CRM_OP_JOIN_OFFER	"join_offer"
 #  define CRM_OP_JOIN_REQUEST	"join_request"
 #  define CRM_OP_JOIN_ACKNAK	"join_ack_nack"
 #  define CRM_OP_JOIN_CONFIRM	"join_confirm"
 #  define CRM_OP_PING		"ping"
 #  define CRM_OP_NODE_INFO  "node-info"
 #  define CRM_OP_THROTTLE	"throttle"
 #  define CRM_OP_VOTE		"vote"
 #  define CRM_OP_NOVOTE		"no-vote"
 #  define CRM_OP_HELLO		"hello"
 #  define CRM_OP_PECALC		"pe_calc"
 #  define CRM_OP_QUIT		"quit"
 #  define CRM_OP_SHUTDOWN_REQ	"req_shutdown"
 #  define CRM_OP_SHUTDOWN   PCMK_ACTION_DO_SHUTDOWN
 #  define CRM_OP_REGISTER		"register"
 #  define CRM_OP_IPC_FWD		"ipc_fwd"
 #  define CRM_OP_INVOKE_LRM	"lrm_invoke"
 #  define CRM_OP_LRM_REFRESH "lrm_refresh" //!< Deprecated since 1.1.10
 #  define CRM_OP_LRM_DELETE         PCMK_ACTION_LRM_DELETE
 #  define CRM_OP_LRM_FAIL		"lrm_fail"
 #  define CRM_OP_PROBED		"probe_complete"
 #  define CRM_OP_REPROBE		"probe_again"
 #  define CRM_OP_CLEAR_FAILCOUNT    PCMK_ACTION_CLEAR_FAILCOUNT
 #  define CRM_OP_REMOTE_STATE     "remote_state"
 #  define CRM_OP_RM_NODE_CACHE "rm_node_cache"
 #  define CRM_OP_MAINTENANCE_NODES  PCMK_ACTION_MAINTENANCE_NODES
 
 /* Possible cluster membership states */
 #  define CRMD_JOINSTATE_DOWN           "down"
 #  define CRMD_JOINSTATE_PENDING        "pending"
 #  define CRMD_JOINSTATE_MEMBER         "member"
 #  define CRMD_JOINSTATE_NACK           "banned"
 
 #  include <crm/common/actions.h>
 #  include <crm/common/cib.h>
 #  include <crm/common/logging.h>
 #  include <crm/common/util.h>
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/crm_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/crm_compat.h b/include/crm/crm_compat.h
index 476804b3bc..a5f2b6e8dd 100644
--- a/include/crm/crm_compat.h
+++ b/include/crm/crm_compat.h
@@ -1,218 +1,220 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CRM_COMPAT__H
 #  define PCMK__CRM_CRM_COMPAT__H
 
 #include <strings.h>
 #include <glib.h>
 
 #include <crm/common/actions.h>
 #include <crm/common/scores.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker utilities
  * \ingroup core
  * \deprecated Do not include this header directly. The utilities in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Use '\0' instead
 #define EOS '\0'
 
 //! \deprecated This defined constant will be removed in a future release
 #define MAX_IPC_DELAY 120
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use PCMK_SCORE_INFINITY instead
 #define CRM_SCORE_INFINITY PCMK_SCORE_INFINITY
 
 /* INFINITY might be defined elsewhere (such as math.h), so undefine it first.
  * This, of course, complicates any attempt to use the other definition in any
  * code that includes this header.
  */
 //! \deprecated Use PCMK_SCORE_INFINITY instead
 #undef INFINITY
 #define INFINITY PCMK_SCORE_INFINITY
 
 //! \deprecated Use PCMK_VALUE_INFINITY instead
 #define CRM_INFINITY_S PCMK_VALUE_INFINITY
 
 //! \deprecated Use PCMK_VALUE_MINUS_INFINITY instead
 #define CRM_MINUS_INFINITY_S PCMK_VALUE_MINUS_INFINITY
 
 //! \deprecated Use PCMK_VALUE_PLUS_INFINITY instead
 #define CRM_PLUS_INFINITY_S PCMK_VALUE_PLUS_INFINITY
 
 //! \deprecated Use PCMK_VALUE_INFINITY instead
 #define INFINITY_S "INFINITY"
 
 //! \deprecated Use PCMK_VALUE_MINUS_INFINITY instead
 #define MINUS_INFINITY_S "-INFINITY"
 
 //! \deprecated Use PCMK_ACTION_STONITH instead
 #define CRM_OP_FENCE PCMK_ACTION_STONITH
 
 //! \deprecated This defined constant will be removed in a future release
 #define CRM_OP_LRM_QUERY "lrm_query"
 
 //! \deprecated Use PCMK_ACTION_CLONE_ONE_OR_MORE instead
 #define CRM_OP_RELAXED_CLONE PCMK_ACTION_CLONE_ONE_OR_MORE
 
 //! \deprecated Use PCMK_ACTION_ONE_OR_MORE instead
 #define CRM_OP_RELAXED_SET PCMK_ACTION_ONE_OR_MORE
 
 //! \deprecated This defined constant will be removed in a future release
 #define CRM_ATTR_RA_VERSION "#ra-version"
 
 //! \deprecated Use PCMK_ACTION_CANCEL instead
 #define CRMD_ACTION_CANCEL PCMK_ACTION_CANCEL
 
 //! \deprecated Use PCMK_ACTION_DELETE instead
 #define CRMD_ACTION_DELETE PCMK_ACTION_DELETE
 
 //! \deprecated Use PCMK_ACTION_DEMOTE instead
 #define CRMD_ACTION_DEMOTE PCMK_ACTION_DEMOTE
 
 //! \deprecated Use PCMK_ACTION_DEMOTED instead
 #define CRMD_ACTION_DEMOTED PCMK_ACTION_DEMOTED
 
 //! \deprecated Use PCMK_ACTION_META_DATA instead
 #define CRMD_ACTION_METADATA PCMK_ACTION_META_DATA
 
 //! \deprecated Use PCMK_ACTION_MIGRATE_TO instead
 #define CRMD_ACTION_MIGRATE PCMK_ACTION_MIGRATE_TO
 
 //! \deprecated Use PCMK_ACTION_MIGRATE_FROM instead
 #define CRMD_ACTION_MIGRATED PCMK_ACTION_MIGRATE_FROM
 
 //! \deprecated Use PCMK_ACTION_NOTIFIED instead
 #define CRMD_ACTION_NOTIFIED PCMK_ACTION_NOTIFIED
 
 //! \deprecated Use PCMK_ACTION_NOTIFY instead
 #define CRMD_ACTION_NOTIFY PCMK_ACTION_NOTIFY
 
 //! \deprecated Use PCMK_ACTION_PROMOTE instead
 #define CRMD_ACTION_PROMOTE PCMK_ACTION_PROMOTE
 
 //! \deprecated Use PCMK_ACTION_PROMOTED instead
 #define CRMD_ACTION_PROMOTED PCMK_ACTION_PROMOTED
 
 //! \deprecated Use PCMK_ACTION_RELOAD instead
 #define CRMD_ACTION_RELOAD PCMK_ACTION_RELOAD
 
 //! \deprecated Use PCMK_ACTION_RELOAD_AGENT instead
 #define CRMD_ACTION_RELOAD_AGENT PCMK_ACTION_RELOAD_AGENT
 
 //! \deprecated Use PCMK_ACTION_START instead
 #define CRMD_ACTION_START PCMK_ACTION_START
 
 //! \deprecated Use PCMK_ACTION_RUNNING instead
 #define CRMD_ACTION_STARTED PCMK_ACTION_RUNNING
 
 //! \deprecated Use PCMK_ACTION_MONITOR instead
 #define CRMD_ACTION_STATUS PCMK_ACTION_MONITOR
 
 //! \deprecated Use PCMK_ACTION_STOP instead
 #define CRMD_ACTION_STOP PCMK_ACTION_STOP
 
 //! \deprecated Use PCMK_ACTION_STOPPED instead
 #define CRMD_ACTION_STOPPED PCMK_ACTION_STOPPED
 
 //! \deprecated Do not use
 #define CRMD_METADATA_CALL_TIMEOUT PCMK_DEFAULT_METADATA_TIMEOUT_MS
 
 //! \deprecated Use PCMK_ACTION_CANCEL instead
 #define RSC_CANCEL PCMK_ACTION_CANCEL
 
 //! \deprecated Use PCMK_ACTION_DELETE instead
 #define RSC_DELETE PCMK_ACTION_DELETE
 
 //! \deprecated Use PCMK_ACTION_DEMOTE instead
 #define RSC_DEMOTE PCMK_ACTION_DEMOTE
 
 //! \deprecated Use PCMK_ACTION_DEMOTED instead
 #define RSC_DEMOTED PCMK_ACTION_DEMOTED
 
 //! \deprecated Use PCMK_ACTION_META_DATA instead
 #define RSC_METADATA PCMK_ACTION_META_DATA
 
 //! \deprecated Use PCMK_ACTION_MIGRATE_TO instead
 #define RSC_MIGRATE PCMK_ACTION_MIGRATE_TO
 
 //! \deprecated Use PCMK_ACTION_MIGRATE_FROM instead
 #define RSC_MIGRATED PCMK_ACTION_MIGRATE_FROM
 
 //! \deprecated Use PCMK_ACTION_NOTIFIED instead
 #define RSC_NOTIFIED PCMK_ACTION_NOTIFIED
 
 //! \deprecated Use PCMK_ACTION_NOTIFY instead
 #define RSC_NOTIFY PCMK_ACTION_NOTIFY
 
 //! \deprecated Use PCMK_ACTION_PROMOTE instead
 #define RSC_PROMOTE PCMK_ACTION_PROMOTE
 
 //! \deprecated Use PCMK_ACTION_PROMOTED instead
 #define RSC_PROMOTED PCMK_ACTION_PROMOTED
 
 //! \deprecated Use PCMK_ACTION_START instead
 #define RSC_START PCMK_ACTION_START
 
 //! \deprecated Use PCMK_ACTION_RUNNING instead
 #define RSC_STARTED PCMK_ACTION_RUNNING
 
 //! \deprecated Use PCMK_ACTION_MONITOR instead
 #define RSC_STATUS PCMK_ACTION_MONITOR
 
 //! \deprecated Use PCMK_ACTION_STOP instead
 #define RSC_STOP PCMK_ACTION_STOP
 
 //! \deprecated Use PCMK_ACTION_STOPPED instead
 #define RSC_STOPPED PCMK_ACTION_STOPPED
 
 //! \deprecated Do not use
 #define CRM_OP_LOCAL_SHUTDOWN "start_shutdown"
 
 //!@{
 //! \deprecated This macro will be removed in a future release
 
 #  ifndef __GNUC__
 #    define __builtin_expect(expr, result) (expr)
 #  endif
 
 #define __likely(expr) __builtin_expect(expr, 1)
 
 #define __unlikely(expr) __builtin_expect(expr, 0)
 
 // This ends the doxygen deprecation comment
 //!@}
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use GList * instead
 typedef GList *GListPtr;
 
 //! \deprecated Do not use
 static inline const char *
 crm_action_str(const char *task, guint interval_ms) {
     if ((task != NULL) && (interval_ms == 0)
         && (strcasecmp(task, PCMK_ACTION_MONITOR) == 0)) {
         return "probe";
     }
     return task;
 }
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_CRM_COMPAT__H
diff --git a/include/crm/msg_xml_compat.h b/include/crm/msg_xml_compat.h
index af75ad1267..e4170b375e 100644
--- a/include/crm/msg_xml_compat.h
+++ b/include/crm/msg_xml_compat.h
@@ -1,1021 +1,1022 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_MSG_XML_COMPAT__H
 #  define PCMK__CRM_MSG_XML_COMPAT__H
 
 #include <crm/common/agents.h>      // PCMK_STONITH_PROVIDES
 #include <crm/common/xml.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker XML constants API
  * \ingroup core
  * \deprecated Do not include this header directly. The XML constants in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Use PCMK_META_CLONE_MAX instead
 #define XML_RSC_ATTR_INCARNATION_MAX PCMK_META_CLONE_MAX
 
 //! \deprecated Use PCMK_META_CLONE_MIN instead
 #define XML_RSC_ATTR_INCARNATION_MIN PCMK_META_CLONE_MIN
 
 //! \deprecated Use PCMK_META_CLONE_NODE_MAX instead
 #define XML_RSC_ATTR_INCARNATION_NODEMAX PCMK_META_CLONE_NODE_MAX
 
 //! \deprecated Use PCMK_META_PROMOTED_MAX instead
 #define XML_RSC_ATTR_PROMOTED_MAX PCMK_META_PROMOTED_MAX
 
 //! \deprecated Use PCMK_META_PROMOTED_NODE_MAX instead
 #define XML_RSC_ATTR_PROMOTED_NODEMAX PCMK_META_PROMOTED_NODE_MAX
 
 //! \deprecated Use PCMK_STONITH_PROVIDES instead
 #define XML_RSC_ATTR_PROVIDES PCMK_STONITH_PROVIDES
 
 //! \deprecated Do not use
 #define PCMK_XE_PROMOTABLE_LEGACY "master"
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_MASTER PCMK_XE_PROMOTABLE_LEGACY
 
 //! \deprecated Do not use
 #define PCMK_XA_PROMOTED_MAX_LEGACY "master-max"
 
 //! \deprecated Do not use
 #define PCMK_XE_PROMOTED_MAX_LEGACY PCMK_XA_PROMOTED_MAX_LEGACY
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_MASTER_MAX PCMK_XA_PROMOTED_MAX_LEGACY
 
 //! \deprecated Do not use
 #define PCMK_XA_PROMOTED_NODE_MAX_LEGACY "master-node-max"
 
 //! \deprecated Do not use
 #define PCMK_XE_PROMOTED_NODE_MAX_LEGACY PCMK_XA_PROMOTED_NODE_MAX_LEGACY
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_MASTER_NODEMAX PCMK_XA_PROMOTED_NODE_MAX_LEGACY
 
 //! \deprecated Use PCMK_META_MIGRATION_THRESHOLD instead
 #define XML_RSC_ATTR_FAIL_STICKINESS PCMK_META_MIGRATION_THRESHOLD
 
 //! \deprecated Use PCMK_META_FAILURE_TIMEOUT instead
 #define XML_RSC_ATTR_FAIL_TIMEOUT PCMK_META_FAILURE_TIMEOUT
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_ATTR_RA_VERSION "ra-version"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_TAG_FRAGMENT "cib_fragment"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_TAG_RSC_VER_ATTRS "rsc_versioned_attrs"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_TAG_OP_VER_ATTRS "op_versioned_attrs"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_TAG_OP_VER_META "op_versioned_meta"
 
 //! \deprecated Use \p PCMK_XA_ID instead
 #define XML_ATTR_UUID "id"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_ATTR_VERBOSE "verbose"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_CIB_TAG_DOMAINS "domains"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_CIB_ATTR_SOURCE "source"
 
 //! \deprecated Do not use
 #define XML_NODE_EXPECTED "expected"
 
 //! \deprecated Do not use
 #define XML_NODE_IN_CLUSTER "in_ccm"
 
 //! \deprecated Do not use
 #define XML_NODE_IS_PEER "crmd"
 
 //! \deprecated Do not use
 #define XML_NODE_JOIN_STATE "join"
 
 //! \deprecated Do not use (will be removed in a future release)
 #define XML_RSC_OP_LAST_RUN "last-run"
 
 //! \deprecated Use name member directly
 #define TYPE(x) (((x) == NULL)? NULL : (const char *) ((x)->name))
 
 //! \deprecated Use \c PCMK_OPT_CLUSTER_RECHECK_INTERVAL instead
 #define XML_CONFIG_ATTR_RECHECK PCMK_OPT_CLUSTER_RECHECK_INTERVAL
 
 //! \deprecated Use \c PCMK_OPT_DC_DEADTIME instead
 #define XML_CONFIG_ATTR_DC_DEADTIME PCMK_OPT_DC_DEADTIME
 
 //! \deprecated Use \c PCMK_OPT_ELECTION_TIMEOUT instead
 #define XML_CONFIG_ATTR_ELECTION_FAIL PCMK_OPT_ELECTION_TIMEOUT
 
 //! \deprecated Use \c PCMK_OPT_FENCE_REACTION instead
 #define XML_CONFIG_ATTR_FENCE_REACTION PCMK_OPT_FENCE_REACTION
 
 //! \deprecated Use \c PCMK_OPT_HAVE_WATCHDOG instead
 #define XML_ATTR_HAVE_WATCHDOG PCMK_OPT_HAVE_WATCHDOG
 
 //! \deprecated Use \c PCMK_OPT_NODE_PENDING_TIMEOUT instead
 #define XML_CONFIG_ATTR_NODE_PENDING_TIMEOUT PCMK_OPT_NODE_PENDING_TIMEOUT
 
 //! \deprecated Use \c PCMK_OPT_PRIORITY_FENCING_DELAY instead
 #define XML_CONFIG_ATTR_PRIORITY_FENCING_DELAY PCMK_OPT_PRIORITY_FENCING_DELAY
 
 //! \deprecated Use \c PCMK_OPT_SHUTDOWN_ESCALATION instead
 #define XML_CONFIG_ATTR_FORCE_QUIT PCMK_OPT_SHUTDOWN_ESCALATION
 
 //! \deprecated Use \c PCMK_OPT_SHUTDOWN_LOCK instead
 #define XML_CONFIG_ATTR_SHUTDOWN_LOCK PCMK_OPT_SHUTDOWN_LOCK
 
 //! \deprecated Use \c PCMK_OPT_SHUTDOWN_LOCK_LIMIT instead
 #define XML_CONFIG_ATTR_SHUTDOWN_LOCK_LIMIT PCMK_OPT_SHUTDOWN_LOCK_LIMIT
 
 //! \deprecated Use \c PCMK_XA_CRM_FEATURE_SET instead
 #define XML_ATTR_CRM_VERSION PCMK_XA_CRM_FEATURE_SET
 
 //! \deprecated Do not use
 #define XML_ATTR_DIGEST "digest"
 
 //! \deprecated Use \c PCMK_XA_VALIDATE_WITH instead
 #define XML_ATTR_VALIDATION PCMK_XA_VALIDATE_WITH
 
 //! \deprecated Use \c PCMK_XA_NO_QUORUM_PANIC instead
 #define XML_ATTR_QUORUM_PANIC PCMK_XA_NO_QUORUM_PANIC
 
 //! \deprecated Use \c PCMK_XA_HAVE_QUORUM instead
 #define XML_ATTR_HAVE_QUORUM PCMK_XA_HAVE_QUORUM
 
 //! \deprecated Use \c PCMK_XA_EPOCH instead
 #define XML_ATTR_GENERATION PCMK_XA_EPOCH
 
 //! \deprecated Use \c PCMK_XA_ADMIN_EPOCH instead
 #define XML_ATTR_GENERATION_ADMIN PCMK_XA_ADMIN_EPOCH
 
 //! \deprecated Use \c PCMK_XA_NUM_UPDATES instead
 #define XML_ATTR_NUMUPDATES PCMK_XA_NUM_UPDATES
 
 //! \deprecated Use \c PCMK_XA_CRM_DEBUG_ORIGIN instead
 #define XML_ATTR_ORIGIN PCMK_XA_CRM_DEBUG_ORIGIN
 
 //! \deprecated Use \c PCMK_XA_CRM_TIMESTAMP instead
 #define XML_ATTR_TSTAMP PCMK_XA_CRM_TIMESTAMP
 
 //! \deprecated Use \c PCMK_XA_CIB_LAST_WRITTEN instead
 #define XML_CIB_ATTR_WRITTEN PCMK_XA_CIB_LAST_WRITTEN
 
 //! \deprecated Use \c PCMK_XA_VERSION instead
 #define XML_ATTR_VERSION PCMK_XA_VERSION
 
 //! \deprecated Use \c PCMK_XA_DESCRIPTION instead
 #define XML_ATTR_DESC PCMK_XA_DESCRIPTION
 
 //! \deprecated Use \c PCMK_XA_ID instead
 #define XML_ATTR_ID PCMK_XA_ID
 
 //! \deprecated Use \c PCMK_XA_ID instead
 #define XML_FAILCIB_ATTR_ID PCMK_XA_ID
 
 //! \deprecated Use \c PCMK_META_CONTAINER_ATTRIBUTE_TARGET instead
 #define XML_RSC_ATTR_TARGET PCMK_META_CONTAINER_ATTRIBUTE_TARGET
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_RESTART "restart-type"
 
 //! \deprecated Use \c PCMK_META_ORDERED instead
 #define XML_RSC_ATTR_ORDERED PCMK_META_ORDERED
 
 //! \deprecated Use \c PCMK_META_INTERLEAVE instead
 #define XML_RSC_ATTR_INTERLEAVE PCMK_META_INTERLEAVE
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_INCARNATION "clone"
 
 //! \deprecated Use \c PCMK_META_PROMOTABLE instead
 #define XML_RSC_ATTR_PROMOTABLE PCMK_META_PROMOTABLE
 
 //! \deprecated Use \c PCMK_META_IS_MANAGED instead
 #define XML_RSC_ATTR_MANAGED PCMK_META_IS_MANAGED
 
 //! \deprecated Use \c PCMK_META_TARGET_ROLE instead
 #define XML_RSC_ATTR_TARGET_ROLE PCMK_META_TARGET_ROLE
 
 //! \deprecated Use \c PCMK_META_GLOBALLY_UNIQUE instead
 #define XML_RSC_ATTR_UNIQUE PCMK_META_GLOBALLY_UNIQUE
 
 //! \deprecated Use \c PCMK_META_NOTIFY instead
 #define XML_RSC_ATTR_NOTIFY PCMK_META_NOTIFY
 
 //! \deprecated Use \c PCMK_META_RESOURCE_STICKINESS instead
 #define XML_RSC_ATTR_STICKINESS PCMK_META_RESOURCE_STICKINESS
 
 //! \deprecated Use \c PCMK_META_MULTIPLE_ACTIVE instead
 #define XML_RSC_ATTR_MULTIPLE PCMK_META_MULTIPLE_ACTIVE
 
 //! \deprecated Use \c PCMK_META_REQUIRES instead
 #define XML_RSC_ATTR_REQUIRES PCMK_META_REQUIRES
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_CONTAINER "container"
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_INTERNAL_RSC "internal_rsc"
 
 //! \deprecated Use \c PCMK_META_MAINTENANCE instead
 #define XML_RSC_ATTR_MAINTENANCE PCMK_META_MAINTENANCE
 
 //! \deprecated Use \c PCMK_META_REMOTE_NODE instead
 #define XML_RSC_ATTR_REMOTE_NODE PCMK_META_REMOTE_NODE
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_CLEAR_OP "clear_failure_op"
 
 //! \deprecated Do not use
 #define XML_RSC_ATTR_CLEAR_INTERVAL "clear_failure_interval"
 
 //! \deprecated Use \c PCMK_META_CRITICAL instead
 #define XML_RSC_ATTR_CRITICAL PCMK_META_CRITICAL
 
 //! \deprecated Use \c PCMK_META_ALLOW_MIGRATE instead
 #define XML_OP_ATTR_ALLOW_MIGRATE PCMK_META_ALLOW_MIGRATE
 
 //! \deprecated Use \c PCMK_VALUE_TRUE instead
 #define XML_BOOLEAN_YES PCMK_VALUE_TRUE
 
 //! \deprecated Use \c PCMK_VALUE_FALSE instead
 #define XML_BOOLEAN_NO PCMK_VALUE_FALSE
 
 //! \deprecated Use \c PCMK_REMOTE_RA_ADDR instead
 #define XML_RSC_ATTR_REMOTE_RA_ADDR PCMK_REMOTE_RA_ADDR
 
 //! \deprecated Use \c PCMK_REMOTE_RA_SERVER instead
 #define XML_RSC_ATTR_REMOTE_RA_SERVER PCMK_REMOTE_RA_SERVER
 
 //! \deprecated Use \c PCMK_REMOTE_RA_PORT instead
 #define XML_RSC_ATTR_REMOTE_RA_PORT PCMK_REMOTE_RA_PORT
 
 //! \deprecated Use \c PCMK_REMOTE_RA_RECONNECT_INTERVAL instead
 #define XML_REMOTE_ATTR_RECONNECT_INTERVAL PCMK_REMOTE_RA_RECONNECT_INTERVAL
 
 //! \deprecated Use \c PCMK_XA_NAME instead
 #define XML_ATTR_NAME PCMK_XA_NAME
 
 //! \deprecated Use \c PCMK_XA_NAME instead
 #define XML_NVPAIR_ATTR_NAME PCMK_XA_NAME
 
 //! \deprecated Use \c PCMK_XA_VALUE instead
 #define XML_EXPR_ATTR_VALUE PCMK_XA_VALUE
 
 //! \deprecated Use \c PCMK_XA_VALUE instead
 #define XML_NVPAIR_ATTR_VALUE PCMK_XA_VALUE
 
 //! \deprecated Use \c PCMK_XA_VALUE instead
 #define XML_ALERT_ATTR_REC_VALUE PCMK_XA_VALUE
 
 //! \deprecated Use \c PCMK_XA_ID_REF instead
 #define XML_ATTR_IDREF PCMK_XA_ID_REF
 
 //! \deprecated Do not use
 #define XML_ATTR_ID_LONG "long-id"
 
 //! \deprecated Use \c PCMK_XA_TYPE instead
 #define XML_ATTR_TYPE PCMK_XA_TYPE
 
 //! \deprecated Use \c PCMK_XA_TYPE instead
 #define XML_EXPR_ATTR_TYPE PCMK_XA_TYPE
 
 //! \deprecated Use \c PCMK_XA_PROVIDER instead
 #define XML_AGENT_ATTR_PROVIDER PCMK_XA_PROVIDER
 
 //! \deprecated Use \c PCMK_XA_CLASS instead
 #define XML_AGENT_ATTR_CLASS PCMK_XA_CLASS
 
 //! \deprecated Use \c PCMK_XE_OP instead
 #define XML_ATTR_OP PCMK_XE_OP
 
 //! \deprecated Use \c PCMK_XA_DC_UUID instead
 #define XML_ATTR_DC_UUID PCMK_XA_DC_UUID
 
 //! \deprecated Use \c PCMK_XA_UPDATE_ORIGIN instead
 #define XML_ATTR_UPDATE_ORIG PCMK_XA_UPDATE_ORIGIN
 
 //! \deprecated Use \c PCMK_XA_UPDATE_CLIENT instead
 #define XML_ATTR_UPDATE_CLIENT PCMK_XA_UPDATE_CLIENT
 
 //! \deprecated Use \c PCMK_XA_UPDATE_USER instead
 #define XML_ATTR_UPDATE_USER PCMK_XA_UPDATE_USER
 
 //! \deprecated Use \c PCMK_XA_REQUEST instead
 #define XML_ATTR_REQUEST PCMK_XA_REQUEST
 
 //! \deprecated Do not use
 #define XML_ATTR_RESPONSE "response"
 
 //! \deprecated Use \c PCMK_XA_UNAME instead
 #define XML_ATTR_UNAME PCMK_XA_UNAME
 
 //! \deprecated Use \c PCMK_XA_REFERENCE instead
 #define XML_ATTR_REFERENCE PCMK_XA_REFERENCE
 
 //! \deprecated Use \c PCMK_XA_REFERENCE instead
 #define XML_ACL_ATTR_REF PCMK_XA_REFERENCE
 
 //! \deprecated Use \c PCMK_XA_REFERENCE instead
 #define F_CRM_REFERENCE PCMK_XA_REFERENCE
 
 //! \deprecated Do not use
 #define XML_ATTR_TRANSITION_MAGIC "transition-magic"
 
 //! \deprecated Do not use
 #define XML_ATTR_TRANSITION_KEY	"transition-key"
 
 //! \deprecated Use \c PCMK_XA_INDEX instead
 #define XML_ATTR_STONITH_INDEX PCMK_XA_INDEX
 
 //! \deprecated Use \c PCMK_XA_TARGET instead
 #define XML_ATTR_STONITH_TARGET PCMK_XA_TARGET
 
 //! \deprecated Use \c PCMK_XA_TARGET_VALUE instead
 #define XML_ATTR_STONITH_TARGET_VALUE PCMK_XA_TARGET_VALUE
 
 //! \deprecated Use \c PCMK_XA_TARGET_PATTERN instead
 #define XML_ATTR_STONITH_TARGET_PATTERN PCMK_XA_TARGET_PATTERN
 
 //! \deprecated Use \c PCMK_XA_TARGET_ATTRIBUTE instead
 #define XML_ATTR_STONITH_TARGET_ATTRIBUTE PCMK_XA_TARGET_ATTRIBUTE
 
 //! \deprecated Use \c PCMK_XA_DEVICES instead
 #define XML_ATTR_STONITH_DEVICES PCMK_XA_DEVICES
 
 #ifndef F_ORIG
 //! \deprecated Do not use
 #define F_ORIG "src"
 #endif
 
 //! \deprecated Do not use
 #define F_CRM_HOST_FROM F_ORIG
 
 #ifndef F_SEQ
 //! \deprecated Do not use
 #define F_SEQ "seq"
 #endif
 
 #ifndef F_SUBTYPE
 //! \deprecated Do not use
 #define F_SUBTYPE "subt"
 #endif
 
 //! \deprecated Do not use
 #define F_CRM_MSG_TYPE F_SUBTYPE
 
 #ifndef F_TYPE
 //! \deprecated Do not use
 #define F_TYPE "t"
 #endif
 
 #ifndef F_CLIENTNAME
 //! \deprecated Do not use
 #define	F_CLIENTNAME "cn"
 #endif
 
 #ifndef F_XML_TAGNAME
 //! \deprecated Do not use
 #define F_XML_TAGNAME "__name__"
 #endif
 
 //! \deprecated Use \c PCMK_VALUE_TRUE instead
 #define XML_BOOLEAN_TRUE PCMK_VALUE_TRUE
 
 //! \deprecated Use \c PCMK_VALUE_FALSE instead
 #define XML_BOOLEAN_FALSE PCMK_VALUE_FALSE
 
 //! \deprecated Do not use
 #define F_CRM_TASK "crm_task"
 
 //! \deprecated Do not use
 #define F_CRM_HOST_TO "crm_host_to"
 
 //! \deprecated Do not use
 #define F_CRM_SYS_TO "crm_sys_to"
 
 //! \deprecated Do not use
 #define F_CRM_SYS_FROM "crm_sys_from"
 
 //! \deprecated Use \c PCMK_XA_VERSION instead
 #define F_CRM_VERSION PCMK_XA_VERSION
 
 //! \deprecated Use \c PCMK_XA_ORIGIN instead
 #define F_CRM_ORIGIN PCMK_XA_ORIGIN
 
 //! \deprecated Do not use
 #define F_CRM_USER "crm_user"
 
 //! \deprecated Do not use
 #define F_CRM_JOIN_ID "join_id"
 
 //! \deprecated Do not use
 #define F_CRM_DC_LEAVING "dc-leaving"
 
 //! \deprecated Do not use
 #define F_CRM_ELECTION_ID "election-id"
 
 //! \deprecated Do not use
 #define F_CRM_ELECTION_AGE_S "election-age-sec"
 
 //! \deprecated Do not use
 #define F_CRM_ELECTION_AGE_US "election-age-nano-sec"
 
 //! \deprecated Do not use
 #define F_CRM_ELECTION_OWNER "election-owner"
 
 //! \deprecated Do not use
 #define F_CRM_TGRAPH "crm-tgraph-file"
 
 //! \deprecated Do not use
 #define F_CRM_TGRAPH_INPUT "crm-tgraph-in"
 
 //! \deprecated Do not use
 #define F_CRM_THROTTLE_MODE "crm-limit-mode"
 
 //! \deprecated Do not use
 #define F_CRM_THROTTLE_MAX "crm-limit-max"
 
 //! \deprecated Use \c PCMK_XA_RESULT instead
 #define XML_PING_ATTR_STATUS PCMK_XA_RESULT
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_SYSFROM "crm_subsystem"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_CRMDSTATE "crmd_state"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE "pacemakerd_state"
 
 //! \deprecated Do not use
 #define XML_FAILCIB_ATTR_OBJTYPE "object_type"
 
 //! \deprecated Use \c PCMK_XA_OPERATION instead
 #define XML_FAILCIB_ATTR_OP PCMK_XA_OPERATION
 
 //! \deprecated Use \c PCMK_XA_OPERATION instead
 #define XML_LRM_ATTR_TASK PCMK_XA_OPERATION
 
 //! \deprecated Use \c PCMK_XA_OPERATION instead
 #define XML_EXPR_ATTR_OPERATION PCMK_XA_OPERATION
 
 //! \deprecated Use \c PCMK_XA_OPERATION instead
 #define XML_DIFF_OP PCMK_XA_OPERATION
 
 //! \deprecated Use \c PCMK_XA_REASON instead
 #define XML_FAILCIB_ATTR_REASON PCMK_XA_REASON
 
 //! \deprecated Use \c PCMK_META_TIMEOUT instead
 #define XML_ATTR_TIMEOUT PCMK_META_TIMEOUT
 
 //! \deprecated Use \c PCMK_META_TIMEOUT instead
 #define XML_ALERT_ATTR_TIMEOUT PCMK_META_TIMEOUT
 
 //! \deprecated Use \c PCMK_XA_PATH instead
 #define XML_ALERT_ATTR_PATH PCMK_XA_PATH
 
 //! \deprecated Use \c PCMK_XA_PATH instead
 #define XML_DIFF_PATH PCMK_XA_PATH
 
 //! \deprecated Use \c PCMK_META_TIMESTAMP_FORMAT instead
 #define XML_ALERT_ATTR_TSTAMP_FORMAT PCMK_META_TIMESTAMP_FORMAT
 
 //! \deprecated Use \c PCMK_META_INTERVAL instead
 #define XML_LRM_ATTR_INTERVAL PCMK_META_INTERVAL
 
 //! \deprecated Use \c PCMK_META_INTERVAL instead
 #define XML_LRM_ATTR_INTERVAL_MS PCMK_META_INTERVAL
 
 //! \deprecated Do not use
 #define XML_CIB_ATTR_REPLACE "replace"
 
 //! \deprecated Do not use
 #define XML_COLOC_ATTR_SOURCE_INSTANCE "rsc-instance"
 
 //! \deprecated Do not use
 #define XML_COLOC_ATTR_TARGET_INSTANCE "with-rsc-instance"
 
 //! \deprecated Use \c PCMK_META_ON_FAIL instead
 #define XML_OP_ATTR_ON_FAIL PCMK_META_ON_FAIL
 
 //! \deprecated Use \c PCMK_META_START_DELAY instead
 #define XML_OP_ATTR_START_DELAY PCMK_META_START_DELAY
 
 //! \deprecated Use \c PCMK_META_INTERVAL_ORIGIN instead
 #define XML_OP_ATTR_ORIGIN PCMK_META_INTERVAL_ORIGIN
 
 //! \deprecated Use \c PCMK_META_RECORD_PENDING instead
 #define XML_OP_ATTR_PENDING PCMK_META_RECORD_PENDING
 
 //! \deprecated Do not use
 #define XML_OP_ATTR_DIGESTS_ALL "digests-all"
 
 //! \deprecated Do not use
 #define XML_OP_ATTR_DIGESTS_SECURE "digests-secure"
 
 //! \deprecated Do not use
 #define XML_CIB_ATTR_PRIORITY "priority"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_TASK_KEY "operation_key"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_TARGET "on_node"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_TARGET_UUID "on_node_uuid"
 
 //! \deprecated Do not use
 #define XML_ORDER_ATTR_FIRST_INSTANCE "first-instance"
 
 //! \deprecated Do not use
 #define XML_ORDER_ATTR_THEN_INSTANCE "then-instance"
 
 //! \deprecated Do not use
 #define XML_TAG_DIFF_ADDED "diff-added"
 
 //! \deprecated Do not use
 #define XML_TAG_DIFF_REMOVED "diff-removed"
 
 //! \deprecated Do not use
 #define XML_ATTR_TE_NOWAIT "op_no_wait"
 
 //! \deprecated Do not use
 #define XML_ATTR_TE_TARGET_RC "op_target_rc"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_ROUTER_NODE "router_node"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_RSCID "rsc-id"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_OPSTATUS "op-status"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_RC "rc-code"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_CALLID "call-id"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_OP_DIGEST "op-digest"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_OP_RESTART "op-force-restart"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_OP_SECURE "op-secure-params"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_RESTART_DIGEST "op-restart-digest"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_SECURE_DIGEST "op-secure-digest"
 
 //! \deprecated Use \c PCMK_XA_EXIT_REASON instead
 #define XML_LRM_ATTR_EXIT_REASON PCMK_XA_EXIT_REASON
 
 //! \deprecated Use \c PCMK_XA_LAST_RC_CHANGE instead
 #define XML_RSC_OP_LAST_CHANGE PCMK_XA_LAST_RC_CHANGE
 
 //! \deprecated Use \c PCMK_XA_EXEC_TIME instead
 #define XML_RSC_OP_T_EXEC PCMK_XA_EXEC_TIME
 
 //! \deprecated Use \c PCMK_XA_QUEUE_TIME instead
 #define XML_RSC_OP_T_QUEUE PCMK_XA_QUEUE_TIME
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_MIGRATE_SOURCE "migrate_source"
 
 //! \deprecated Do not use
 #define XML_LRM_ATTR_MIGRATE_TARGET "migrate_target"
 
 //! \deprecated Use \c PCMK_XA_SCORE instead
 #define XML_RULE_ATTR_SCORE PCMK_XA_SCORE
 
 //! \deprecated Use \c PCMK_XA_SCORE_ATTRIBUTE instead
 #define XML_RULE_ATTR_SCORE_ATTRIBUTE PCMK_XA_SCORE_ATTRIBUTE
 
 //! \deprecated Use \c PCMK_XE_ROLE instead
 #define XML_ACL_TAG_ROLE_REF PCMK_XE_ROLE
 
 //! \deprecated Use \c PCMK_XA_ROLE instead
 #define XML_RULE_ATTR_ROLE PCMK_XA_ROLE
 
 //! \deprecated Use \c PCMK_XA_BOOLEAN_OP instead
 #define XML_RULE_ATTR_BOOLEAN_OP PCMK_XA_BOOLEAN_OP
 
 //! \deprecated Use \c PCMK_XA_ATTRIBUTE instead
 #define XML_EXPR_ATTR_ATTRIBUTE PCMK_XA_ATTRIBUTE
 
 //! \deprecated Use \c PCMK_XA_ATTRIBUTE instead
 #define XML_ACL_ATTR_ATTRIBUTE PCMK_XA_ATTRIBUTE
 
 //! \deprecated Use \c PCMK_XA_VALUE_SOURCE instead
 #define XML_EXPR_ATTR_VALUE_SOURCE PCMK_XA_VALUE_SOURCE
 
 //! \deprecated Use \c PCMK_XA_SYMMETRICAL instead
 #define XML_CONS_ATTR_SYMMETRICAL PCMK_XA_SYMMETRICAL
 
 //! \deprecated Use \c PCMK_XA_RESOURCE_DISCOVERY instead
 #define XML_LOCATION_ATTR_DISCOVERY PCMK_XA_RESOURCE_DISCOVERY
 
 //! \deprecated Use \c PCMK_XE_PARAMETERS instead
 #define XML_TAG_PARAMS PCMK_XE_PARAMETERS
 
 //! \deprecated Use \c PCMK_XA_RSC instead
 #define XML_COLOC_ATTR_SOURCE PCMK_XA_RSC
 
 //! \deprecated Use \c PCMK_XA_RSC instead
 #define XML_LOC_ATTR_SOURCE PCMK_XA_RSC
 
 //! \deprecated Use \c PCMK_XA_RSC_ROLE instead
 #define XML_COLOC_ATTR_SOURCE_ROLE PCMK_XA_RSC_ROLE
 
 //! \deprecated Use \c PCMK_XA_WITH_RSC instead
 #define XML_COLOC_ATTR_TARGET PCMK_XA_WITH_RSC
 
 //! \deprecated Use \c PCMK_XA_WITH_RSC_ROLE instead
 #define XML_COLOC_ATTR_TARGET_ROLE PCMK_XA_WITH_RSC_ROLE
 
 //! \deprecated Use \c PCMK_XA_NODE_ATTRIBUTE instead
 #define XML_COLOC_ATTR_NODE_ATTR PCMK_XA_NODE_ATTRIBUTE
 
 //! \deprecated Use \c PCMK_XA_INFLUENCE instead
 #define XML_COLOC_ATTR_INFLUENCE PCMK_XA_INFLUENCE
 
 //! \deprecated Use \c PCMK_XA_RSC_PATTERN instead
 #define XML_LOC_ATTR_SOURCE_PATTERN PCMK_XA_RSC_PATTERN
 
 //! \deprecated Use \c PCMK_XA_FIRST instead
 #define XML_ORDER_ATTR_FIRST PCMK_XA_FIRST
 
 //! \deprecated Use \c PCMK_XA_THEN instead
 #define XML_ORDER_ATTR_THEN PCMK_XA_THEN
 
 //! \deprecated Use \c PCMK_XA_FIRST_ACTION instead
 #define XML_ORDER_ATTR_FIRST_ACTION PCMK_XA_FIRST_ACTION
 
 //! \deprecated Use \c PCMK_XA_THEN_ACTION instead
 #define XML_ORDER_ATTR_THEN_ACTION PCMK_XA_THEN_ACTION
 
 //! \deprecated Use \c PCMK_XA_KIND instead
 #define XML_ORDER_ATTR_KIND PCMK_XA_KIND
 
 //! \deprecated Use \c PCMK_XA_KIND instead
 #define XML_ACL_ATTR_KIND PCMK_XA_KIND
 
 //! \deprecated Use \c PCMK_XA_TICKET instead
 #define XML_TICKET_ATTR_TICKET PCMK_XA_TICKET
 
 //! \deprecated Use \c PCMK_XA_LOSS_POLICY instead
 #define XML_TICKET_ATTR_LOSS_POLICY PCMK_XA_LOSS_POLICY
 
 //! \deprecated Do not use
 #define XML_ACL_ATTR_REFv1 "ref"
 
 //! \deprecated Use \c PCMK_XA_OBJECT_TYPE instead
 #define XML_ACL_ATTR_TAG PCMK_XA_OBJECT_TYPE
 
 //! \deprecated Do not use
 #define XML_ACL_ATTR_TAGv1 "tag"
 
 //! \deprecated Use \c PCMK_XA_XPATH instead
 #define XML_ACL_ATTR_XPATH PCMK_XA_XPATH
 
 //! \deprecated Do not use
 #define XML_CRM_TAG_PING "ping_response"
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use \c PCMK_XE_CIB instead
 #define XML_TAG_CIB PCMK_XE_CIB
 
 //! \deprecated Use \c PCMK_XE_CONFIGURATION instead
 #define XML_CIB_TAG_CONFIGURATION PCMK_XE_CONFIGURATION
 
 //! \deprecated Use \c PCMK_XE_STATUS instead
 #define XML_CIB_TAG_STATUS PCMK_XE_STATUS
 
 //! \deprecated Use \c PCMK_XE_RESOURCES instead
 #define XML_CIB_TAG_RESOURCES PCMK_XE_RESOURCES
 
 //! \deprecated Use \c PCMK_XE_NODES instead
 #define XML_CIB_TAG_NODES PCMK_XE_NODES
 
 //! \deprecated Use \c PCMK_XE_CONSTRAINTS instead
 #define XML_CIB_TAG_CONSTRAINTS PCMK_XE_CONSTRAINTS
 
 //! \deprecated Use \c PCMK_XE_CRM_CONFIG instead
 #define XML_CIB_TAG_CRMCONFIG PCMK_XE_CRM_CONFIG
 
 //! \deprecated Use \c PCMK_XE_OP_DEFAULTS instead
 #define XML_CIB_TAG_OPCONFIG PCMK_XE_OP_DEFAULTS
 
 //! \deprecated Use \c PCMK_XE_RSC_DEFAULTS instead
 #define XML_CIB_TAG_RSCCONFIG PCMK_XE_RSC_DEFAULTS
 
 //! \deprecated Use \c PCMK_XE_ACLS instead
 #define XML_CIB_TAG_ACLS PCMK_XE_ACLS
 
 //! \deprecated Use \c PCMK_XE_ALERTS instead
 #define XML_CIB_TAG_ALERTS PCMK_XE_ALERTS
 
 //! \deprecated Use \c PCMK_XE_ALERT instead
 #define XML_CIB_TAG_ALERT PCMK_XE_ALERT
 
 //! \deprecated Use \c PCMK_XE_RECIPIENT instead
 #define XML_CIB_TAG_ALERT_RECIPIENT PCMK_XE_RECIPIENT
 
 //! \deprecated Use \c PCMK_XE_SELECT instead
 #define XML_CIB_TAG_ALERT_SELECT PCMK_XE_SELECT
 
 //! \deprecated Use \c PCMK_XE_SELECT_ATTRIBUTES instead
 #define XML_CIB_TAG_ALERT_ATTRIBUTES PCMK_XE_SELECT_ATTRIBUTES
 
 //! \deprecated Use \c PCMK_XE_SELECT_FENCING instead
 #define XML_CIB_TAG_ALERT_FENCING PCMK_XE_SELECT_FENCING
 
 //! \deprecated Use \c PCMK_XE_SELECT_NODES instead
 #define XML_CIB_TAG_ALERT_NODES PCMK_XE_SELECT_NODES
 
 //! \deprecated Use \c PCMK_XE_SELECT_RESOURCES instead
 #define XML_CIB_TAG_ALERT_RESOURCES PCMK_XE_SELECT_RESOURCES
 
 //! \deprecated Use \c PCMK_XE_ATTRIBUTE instead
 #define XML_CIB_TAG_ALERT_ATTR PCMK_XE_ATTRIBUTE
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_STATE "node_state"
 
 //! \deprecated Use \c PCMK_XE_NODE instead
 #define XML_CIB_TAG_NODE PCMK_XE_NODE
 
 //! \deprecated Use \c PCMK_XE_NVPAIR instead
 #define XML_CIB_TAG_NVPAIR PCMK_XE_NVPAIR
 
 //! \deprecated Use \c PCMK_XE_CLUSTER_PROPERTY_SET instead
 #define XML_CIB_TAG_PROPSET PCMK_XE_CLUSTER_PROPERTY_SET
 
 //! \deprecated Use \c PCMK_XE_INSTANCE_ATTRIBUTES instead
 #define XML_TAG_ATTR_SETS PCMK_XE_INSTANCE_ATTRIBUTES
 
 //! \deprecated Use \c PCMK_XE_META_ATTRIBUTES instead
 #define XML_TAG_META_SETS PCMK_XE_META_ATTRIBUTES
 
 //! \deprecated Do not use
 #define XML_TAG_ATTRS "attributes"
 
 //! \deprecated Do not use
 #define XML_TAG_PARAM "param"
 
 //! \deprecated Use \c PCMK_XE_UTILIZATION instead
 #define XML_TAG_UTILIZATION PCMK_XE_UTILIZATION
 
 //! \deprecated Use \c PCMK_XE_RESOURCE_REF instead
 #define XML_TAG_RESOURCE_REF PCMK_XE_RESOURCE_REF
 
 //! \deprecated Use \c PCMK_XE_PRIMITIVE instead
 #define XML_CIB_TAG_RESOURCE PCMK_XE_PRIMITIVE
 
 //! \deprecated Use \c PCMK_XE_GROUP instead
 #define XML_CIB_TAG_GROUP PCMK_XE_GROUP
 
 //! \deprecated Use \c PCMK_XE_CLONE instead
 #define XML_CIB_TAG_INCARNATION PCMK_XE_CLONE
 
 //! \deprecated Use \c PCMK_XE_BUNDLE instead
 #define XML_CIB_TAG_CONTAINER PCMK_XE_BUNDLE
 
 //! \deprecated Use \c PCMK_XE_TEMPLATE instead
 #define XML_CIB_TAG_RSC_TEMPLATE PCMK_XE_TEMPLATE
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_LRM "lrm"
 
 //! \deprecated Do not use
 #define XML_LRM_TAG_RESOURCES "lrm_resources"
 
 //! \deprecated Do not use
 #define XML_LRM_TAG_RESOURCE "lrm_resource"
 
 //! \deprecated Do not use
 #define XML_LRM_TAG_RSC_OP "lrm_rsc_op"
 
 //! \deprecated Do not use
 #define XML_TAG_GRAPH "transition_graph"
 
 //! \deprecated Do not use
 #define XML_GRAPH_TAG_RSC_OP "rsc_op"
 
 //! \deprecated Do not use
 #define XML_GRAPH_TAG_PSEUDO_EVENT "pseudo_event"
 
 //! \deprecated Do not use
 #define XML_GRAPH_TAG_CRM_EVENT "crm_event"
 
 //! \deprecated Do not use
 #define XML_GRAPH_TAG_DOWNED "downed"
 
 //! \deprecated Do not use
 #define XML_GRAPH_TAG_MAINTENANCE "maintenance"
 
 //! \deprecated Use \c PCMK_XE_RULE instead
 #define XML_TAG_RULE PCMK_XE_RULE
 
 //! \deprecated Use \c PCMK_XE_EXPRESSION instead
 #define XML_TAG_EXPRESSION PCMK_XE_EXPRESSION
 
 //! \deprecated Use \c PCMK_XE_RSC_COLOCATION instead
 #define XML_CONS_TAG_RSC_DEPEND PCMK_XE_RSC_COLOCATION
 
 //! \deprecated Use \c PCMK_XE_RSC_ORDER instead
 #define XML_CONS_TAG_RSC_ORDER PCMK_XE_RSC_ORDER
 
 //! \deprecated Use \c PCMK_XE_RSC_LOCATION instead
 #define XML_CONS_TAG_RSC_LOCATION PCMK_XE_RSC_LOCATION
 
 //! \deprecated Use \c PCMK_XE_RSC_TICKET instead
 #define XML_CONS_TAG_RSC_TICKET PCMK_XE_RSC_TICKET
 
 //! \deprecated Use \c PCMK_XE_RESOURCE_SET instead
 #define XML_CONS_TAG_RSC_SET PCMK_XE_RESOURCE_SET
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_GENERATION_TUPPLE "generation_tuple"
 
 //! \deprecated Do not use
 #define XML_TAG_TRANSIENT_NODEATTRS "transient_attributes"
 
 //! \deprecated Use \c PCMK_XE_ACL_TARGET instead
 #define XML_ACL_TAG_USER PCMK_XE_ACL_TARGET
 
 //! \deprecated Do not use
 #define XML_ACL_TAG_USERv1 "acl_user"
 
 //! \deprecated Use \c PCMK_XE_ACL_GROUP instead
 #define XML_ACL_TAG_GROUP PCMK_XE_ACL_GROUP
 
 //! \deprecated Use \c PCMK_XE_ACL_ROLE instead
 #define XML_ACL_TAG_ROLE PCMK_XE_ACL_ROLE
 
 //! \deprecated Use \c PCMK_XE_ACL_PERMISSION instead
 #define XML_ACL_TAG_PERMISSION PCMK_XE_ACL_PERMISSION
 
 //! \deprecated Do not use
 #define XML_ACL_TAG_ROLE_REFv1 "role_ref"
 
 //! \deprecated Do not use
 #define XML_ACL_TAG_READ "read"
 
 //! \deprecated Do not use
 #define XML_ACL_TAG_WRITE "write"
 
 //! \deprecated Do not use
 #define XML_ACL_TAG_DENY "deny"
 
 //! \deprecated Use \c PCMK_XE_TICKETS instead
 #define XML_CIB_TAG_TICKETS PCMK_XE_TICKETS
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_TICKET_STATE "ticket_state"
 
 //! \deprecated Use \c PCMK_XE_TAGS instead
 #define XML_CIB_TAG_TAGS PCMK_XE_TAGS
 
 //! \deprecated Use \c PCMK_XE_TAG instead
 #define XML_CIB_TAG_TAG PCMK_XE_TAG
 
 //! \deprecated Use \c PCMK_XE_OBJ_REF instead
 #define XML_CIB_TAG_OBJ_REF PCMK_XE_OBJ_REF
 
 //! \deprecated Use \c PCMK_XE_FENCING_TOPOLOGY instead
 #define XML_TAG_FENCING_TOPOLOGY PCMK_XE_FENCING_TOPOLOGY
 
 //! \deprecated Use \c PCMK_XE_FENCING_LEVEL instead
 #define XML_TAG_FENCING_LEVEL PCMK_XE_FENCING_LEVEL
 
 //! \deprecated Use \c PCMK_XE_DIFF instead
 #define XML_TAG_DIFF PCMK_XE_DIFF
 
 //! \deprecated Use \c PCMK_XE_VERSION instead
 #define XML_DIFF_VERSION PCMK_XE_VERSION
 
 //! \deprecated Use \c PCMK_XE_SOURCE instead
 #define XML_DIFF_VSOURCE PCMK_XE_SOURCE
 
 //! \deprecated Use \c PCMK_XE_TARGET instead
 #define XML_DIFF_VTARGET PCMK_XE_TARGET
 
 //! \deprecated Use \c PCMK_XE_CHANGE instead
 #define XML_DIFF_CHANGE PCMK_XE_CHANGE
 
 //! \deprecated Use \c PCMK_XE_CHANGE_LIST instead
 #define XML_DIFF_LIST PCMK_XE_CHANGE_LIST
 
 //! \deprecated Use \c PCMK_XE_CHANGE_ATTR instead
 #define XML_DIFF_ATTR PCMK_XE_CHANGE_ATTR
 
 //! \deprecated Use \c PCMK_XE_CHANGE_RESULT instead
 #define XML_DIFF_RESULT PCMK_XE_CHANGE_RESULT
 
 //! \deprecated Use \c PCMK_XE_POSITION instead
 #define XML_DIFF_POSITION PCMK_XE_POSITION
 
 //! \deprecated Do not use
 #define F_CRM_DATA "crm_xml"
 
 //! \deprecated Do not use
 #define XML_DIFF_MARKER "__crm_diff_marker__"
 
 //! \deprecated Do not use
 #define XML_TAG_FAILED "failed"
 
 //! \deprecated Do not use
 #define XML_TAG_OPTIONS "options"
 
 //! \deprecated Do not use
 #define XML_FAIL_TAG_CIB "failed_update"
 
 //! \deprecated Use \c PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS instead
 #define CIB_OPTIONS_FIRST PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_INIT "init"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_STARTINGDAEMONS "starting_daemons"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_WAITPING "wait_for_ping"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_RUNNING "running"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_SHUTTINGDOWN "shutting_down"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_SHUTDOWNCOMPLETE "shutdown_complete"
 
 //! \deprecated Do not use
 #define XML_PING_ATTR_PACEMAKERDSTATE_REMOTE "remote"
 
 #ifndef T_CRM
 //! \deprecated Do not use
 #define T_CRM "crmd"
 #endif
 
 #ifndef T_ATTRD
 //! \deprecated Do not use
 #define T_ATTRD "attrd"
 #endif
 
 //! \deprecated Do not use
 #define XML_CIB_TAG_SECTION_ALL "all"
 
 //! \deprecated Do not use
 #define XML_NODE_IS_REMOTE "remote_node"
 
 //! \deprecated Do not use
 #define XML_NODE_IS_FENCED "node_fenced"
 
 //! \deprecated Do not use
 #define XML_NODE_IS_MAINTENANCE "node_in_maintenance"
 
 //! \deprecated Do not use
 #define XML_CIB_ATTR_SHUTDOWN "shutdown"
 
 //! \deprecated Do not use
 #define XML_NODE_ATTR_RSC_DISCOVERY "resource-discovery-enabled"
 
 //! \deprecated Do not use
 #define ID(x) crm_element_value(x, PCMK_XA_ID)
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_MSG_XML_COMPAT__H
diff --git a/include/crm/pengine/pe_types_compat.h b/include/crm/pengine/pe_types_compat.h
index 241363562f..30b7590997 100644
--- a/include/crm/pengine/pe_types_compat.h
+++ b/include/crm/pengine/pe_types_compat.h
@@ -1,266 +1,272 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_PENGINE_PE_TYPES_COMPAT__H
 #  define PCMK__CRM_PENGINE_PE_TYPES_COMPAT__H
 
 #include <crm/common/scheduler.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker scheduler API
  * \ingroup pengine
  * \deprecated Do not include this header directly. The scheduler APIs in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
 //! \deprecated Do not use
 #define pe_rsc_orphan                   pcmk_rsc_removed
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Do not use
 #define pe_rsc_managed                  pcmk_rsc_managed
 
 //! \deprecated Do not use
 #define pe_rsc_block                    pcmk_rsc_blocked
 
 //! \deprecated Do not use
 #define pe_rsc_orphan_container_filler  pcmk_rsc_removed_filler
 
 //! \deprecated Do not use
 #define pe_rsc_notify                   pcmk_rsc_notify
 
 //! \deprecated Do not use
 #define pe_rsc_unique                   pcmk_rsc_unique
 
 //! \deprecated Do not use
 #define pe_rsc_fence_device             pcmk_rsc_fence_device
 
 //! \deprecated Do not use
 #define pe_rsc_promotable               pcmk_rsc_promotable
 
 //! \deprecated Do not use
 #define pe_rsc_provisional              pcmk_rsc_unassigned
 
 //! \deprecated Do not use
 #define pe_rsc_allocating               pcmk_rsc_assigning
 
 //! \deprecated Do not use
 #define pe_rsc_merging                  pcmk_rsc_updating_nodes
 
 //! \deprecated Do not use
 #define pe_rsc_restarting               pcmk_rsc_restarting
 
 //! \deprecated Do not use
 #define pe_rsc_stop                     pcmk_rsc_stop_if_failed
 
 //! \deprecated Do not use
 #define pe_rsc_reload                   pcmk_rsc_reload
 
 //! \deprecated Do not use
 #define pe_rsc_allow_remote_remotes     pcmk_rsc_remote_nesting_allowed
 
 //! \deprecated Do not use
 #define pe_rsc_critical                 pcmk_rsc_critical
 
 //! \deprecated Do not use
 #define pe_rsc_failed                   pcmk_rsc_failed
 
 //! \deprecated Do not use
 #define pe_rsc_detect_loop              pcmk_rsc_detect_loop
 
 //! \deprecated Do not use
 #define pe_rsc_runnable                 pcmk_rsc_runnable
 
 //! \deprecated Do not use
 #define pe_rsc_start_pending            pcmk_rsc_start_pending
 
 //!< \deprecated Do not use
 #define pe_rsc_starting                 pcmk_rsc_starting
 
 //!< \deprecated Do not use
 #define pe_rsc_stopping                 pcmk_rsc_stopping
 
 //! \deprecated Do not use
 #define pe_rsc_stop_unexpected          pcmk_rsc_stop_unexpected
 
 //! \deprecated Do not use
 #define pe_rsc_allow_migrate            pcmk_rsc_migratable
 
 //! \deprecated Do not use
 #define pe_rsc_failure_ignored          pcmk_rsc_ignore_failure
 
 //! \deprecated Do not use
 #define pe_rsc_replica_container        pcmk_rsc_replica_container
 
 //! \deprecated Do not use
 #define pe_rsc_maintenance              pcmk_rsc_maintenance
 
 //! \deprecated Do not use
 #define pe_rsc_is_container             pcmk_rsc_has_filler
 
 //! \deprecated Do not use
 #define pe_rsc_needs_quorum             pcmk_rsc_needs_quorum
 
 //! \deprecated Do not use
 #define pe_rsc_needs_fencing            pcmk_rsc_needs_fencing
 
 //! \deprecated Do not use
 #define pe_rsc_needs_unfencing          pcmk_rsc_needs_unfencing
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_sched_quorate instead
 #define pe_flag_have_quorum             pcmk_sched_quorate
 
 //! \deprecated Use pcmk_sched_symmetric_cluster instead
 #define pe_flag_symmetric_cluster       pcmk_sched_symmetric_cluster
 
 //! \deprecated Use pcmk_sched_in_maintenance instead
 #define pe_flag_maintenance_mode        pcmk_sched_in_maintenance
 
 //! \deprecated Use pcmk_sched_fencing_enabled instead
 #define pe_flag_stonith_enabled         pcmk_sched_fencing_enabled
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_sched_have_fencing instead
 #define pe_flag_have_stonith_resource   pcmk_sched_have_fencing
 
 //! \deprecated Use pcmk_sched_enable_unfencing instead
 #define pe_flag_enable_unfencing        pcmk_sched_enable_unfencing
 
 //! \deprecated Use pcmk_sched_concurrent_fencing instead
 #define pe_flag_concurrent_fencing      pcmk_sched_concurrent_fencing
 
 //! \deprecated Use pcmk_sched_stop_removed_resources instead
 #define pe_flag_stop_rsc_orphans        pcmk_sched_stop_removed_resources
 
 //! \deprecated Use pcmk_sched_cancel_removed_actions instead
 #define pe_flag_stop_action_orphans     pcmk_sched_cancel_removed_actions
 
 //! \deprecated Use pcmk_sched_stop_all instead
 #define pe_flag_stop_everything         pcmk_sched_stop_all
 
 //! \deprecated Use pcmk_sched_start_failure_fatal instead
 #define pe_flag_start_failure_fatal     pcmk_sched_start_failure_fatal
 
 //! \deprecated Do not use
 #define pe_flag_remove_after_stop       pcmk_sched_remove_after_stop
 
 //! \deprecated Use pcmk_sched_startup_fencing instead
 #define pe_flag_startup_fencing         pcmk_sched_startup_fencing
 
 //! \deprecated Use pcmk_sched_shutdown_lock instead
 #define pe_flag_shutdown_lock           pcmk_sched_shutdown_lock
 
 //! \deprecated Use pcmk_sched_probe_resources instead
 #define pe_flag_startup_probes          pcmk_sched_probe_resources
 
 //! \deprecated Use pcmk_sched_have_status instead
 #define pe_flag_have_status             pcmk_sched_have_status
 
 //! \deprecated Use pcmk_sched_have_remote_nodes instead
 #define pe_flag_have_remote_nodes       pcmk_sched_have_remote_nodes
 
 //! \deprecated Use pcmk_sched_location_only instead
 #define pe_flag_quick_location          pcmk_sched_location_only
 
 //! \deprecated Use pcmk_sched_sanitized instead
 #define pe_flag_sanitized               pcmk_sched_sanitized
 
 //! \deprecated Do not use
 #define pe_flag_stdout                  (1ULL << 22)
 
 //! \deprecated Use pcmk_sched_no_counts instead
 #define pe_flag_no_counts               pcmk_sched_no_counts
 
 //! \deprecated Use pcmk_sched_no_compat instead
 #define pe_flag_no_compat               pcmk_sched_no_compat
 
 //! \deprecated Use pcmk_sched_output_scores instead
 #define pe_flag_show_scores             pcmk_sched_output_scores
 
 //! \deprecated Use pcmk_sched_show_utilization instead
 #define pe_flag_show_utilization        pcmk_sched_show_utilization
 
 //! \deprecated Use pcmk_sched_validate_only instead
 #define pe_flag_check_config            pcmk_sched_validate_only
 
 //!@{
 //! \deprecated Do not use (unused by Pacemaker)
 enum pe_graph_flags {
     pe_graph_none = 0x00000,
     pe_graph_updated_first = 0x00001,
     pe_graph_updated_then = 0x00002,
     pe_graph_disable = 0x00004,
 };
 //!@}
 
 //!@{
 //! \deprecated Do not use
 enum pe_check_parameters {
     pe_check_last_failure,
     pe_check_active,
 };
 //!@}
 
 //! \deprecated Use pcmk_action_t instead
 typedef struct pe_action_s action_t;
 
 //! \deprecated Use pcmk_action_t instead
 typedef struct pe_action_s pe_action_t;
 
 //! \deprecated Do not use
 typedef struct pe_action_wrapper_s action_wrapper_t;
 
 //! \deprecated Do not use
 typedef struct pe_action_wrapper_s pe_action_wrapper_t;
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_node_t instead
 typedef struct pe_node_s node_t;
 
 //! \deprecated Use pcmk_node_t instead
 typedef struct pe_node_s pe_node_t;
 
 //! \deprecated Use enum pe_quorum_policy instead
 typedef enum pe_quorum_policy no_quorum_policy_t;
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated use pcmk_resource_t instead
 typedef struct pe_resource_s resource_t;
 
 //! \deprecated use pcmk_resource_t instead
 typedef struct pe_resource_s pe_resource_t;
 
 //! \deprecated Do not use
 typedef struct pe_tag_s tag_t;
 
 //! \deprecated Do not use
 typedef struct pe_tag_s pe_tag_t;
 
 //! \deprecated Do not use
 typedef struct pe_ticket_s ticket_t;
 
 //! \deprecated Do not use
 typedef struct pe_ticket_s pe_ticket_t;
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_scheduler_t instead
 typedef struct pe_working_set_s pe_working_set_t;
 
 //! \deprecated This type should be treated as internal to Pacemaker
 typedef struct resource_alloc_functions_s resource_alloc_functions_t;
 
 //! \deprecated Use pcmk_rsc_methods_t instead
 typedef struct resource_object_functions_s resource_object_functions_t;
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_PENGINE_PE_TYPES_COMPAT__H
diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h
index 4ed877bc7b..037d3fa62a 100644
--- a/include/crm/pengine/status.h
+++ b/include/crm/pengine/status.h
@@ -1,58 +1,68 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_PENGINE_STATUS__H
 #  define PCMK__CRM_PENGINE_STATUS__H
 
 #  include <glib.h>                 // gboolean
 #  include <stdbool.h>              // bool
 #  include <crm/common/util.h>      // pcmk_is_set()
 #  include <crm/common/iso8601.h>
 #  include <crm/pengine/common.h>
 #  include <crm/pengine/pe_types.h> // pcmk_node_t, pcmk_resource_t, etc.
 #  include <crm/pengine/complex.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*!
  * \file
  * \brief Cluster status and scheduling
  * \ingroup pengine
  */
 
 const char *rsc_printable_id(const pcmk_resource_t *rsc);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 gboolean cluster_status(pcmk_scheduler_t *scheduler);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 pcmk_scheduler_t *pe_new_working_set(void);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 void pe_free_working_set(pcmk_scheduler_t *scheduler);
+
 void set_working_set_defaults(pcmk_scheduler_t *scheduler);
 void cleanup_calculations(pcmk_scheduler_t *scheduler);
+
+// NOTE: sbd (as of at least 1.5.2) uses this
 void pe_reset_working_set(pcmk_scheduler_t *scheduler);
+
 pcmk_resource_t *pe_find_resource(GList *rsc_list, const char *id_rh);
 pcmk_resource_t *pe_find_resource_with_flags(GList *rsc_list, const char *id,
                                              enum pe_find flags);
 pcmk_node_t *pe_find_node_id(const GList *node_list, const char *id);
 pcmk_node_t *pe_find_node_any(const GList *node_list, const char *id,
                             const char *node_name);
 GList *find_operations(const char *rsc, const char *node, gboolean active_filter,
                          pcmk_scheduler_t *scheduler);
 void calculate_active_ops(const GList *sorted_op_list, int *start_index,
                           int *stop_index);
 int pe_bundle_replicas(const pcmk_resource_t *rsc);
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/pengine/status_compat.h>
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm/pengine/status_compat.h b/include/crm/pengine/status_compat.h
index 9f419581c0..1ff55066e8 100644
--- a/include/crm/pengine/status_compat.h
+++ b/include/crm/pengine/status_compat.h
@@ -1,71 +1,72 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_PENGINE_STATUS_COMPAT__H
 #define PCMK__CRM_PENGINE_STATUS_COMPAT__H
 
 #include <stdbool.h>                // bool
 #include <crm/common/util.h>        // pcmk_is_set()
 #include <crm/common/scheduler.h>   // pcmk_resource_t, pcmk_rsc_unique, etc.
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Deprecated Pacemaker scheduler utilities
  * \ingroup pengine
  * \deprecated Do not include this header directly. The utilities in this
  *             header, and the header itself, will be removed in a future
  *             release.
  */
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 //! \deprecated Use pcmk_find_node() with scheduler object instead
 pcmk_node_t *pe_find_node(const GList *node_list, const char *node_name);
 
 //! \deprecated Compare variant directly instead
 static inline bool
 pe_rsc_is_clone(const pcmk_resource_t *rsc)
 {
     return (rsc != NULL) && (rsc->variant == pcmk_rsc_variant_clone);
 }
 
 //! \deprecated Compare variant and flags directly
 static inline bool
 pe_rsc_is_unique_clone(const pcmk_resource_t *rsc)
 {
     return pe_rsc_is_clone(rsc) && pcmk_is_set(rsc->flags, pcmk_rsc_unique);
 }
 
 //! \deprecated Compare variant and flags directly
 static inline bool
 pe_rsc_is_anon_clone(const pcmk_resource_t *rsc)
 {
     return pe_rsc_is_clone(rsc) && !pcmk_is_set(rsc->flags, pcmk_rsc_unique);
 }
 
 //! \deprecated Compare ancestor variants directly
 static inline bool
 pe_rsc_is_bundled(const pcmk_resource_t *rsc)
 {
     if (rsc == NULL) {
         return false;
     }
     while (rsc->parent != NULL) {
         rsc = rsc->parent;
     }
     return rsc->variant == pcmk_rsc_variant_bundle;
 }
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif // PCMK__CRM_PENGINE_STATUS_COMPAT__H
diff --git a/include/crm/services.h b/include/crm/services.h
index 4f0a5f03fc..b6e3a7013a 100644
--- a/include/crm/services.h
+++ b/include/crm/services.h
@@ -1,432 +1,437 @@
 /*
  * Copyright 2010-2023 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_SERVICES__H
 #  define PCMK__CRM_SERVICES__H
 
 
 #  include <glib.h>
 #  include <stdio.h>
 #  include <stdint.h>
 #  include <string.h>
 #  include <stdbool.h>
 #  include <sys/types.h>
 
 #  include <crm_config.h>       // OCF_ROOT_DIR
 #  include <crm/common/agents.h>
 #  include <crm/common/results.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+// NOTE: booth (as of at least 1.1) checks for the existence of this header
+
 /*!
  * \file
  * \brief Services API
  * \ingroup core
  */
 
 /* TODO: Autodetect these two ?*/
 #  ifndef SYSTEMCTL
 #    define SYSTEMCTL "/bin/systemctl"
 #  endif
 
 /* This is the string passed in the OCF_EXIT_REASON_PREFIX environment variable.
  * The stderr output that occurs after this prefix is encountered is considered
  * the exit reason for a completed operation.
  */
 #define PCMK_OCF_REASON_PREFIX "ocf-exit-reason:"
 
 // Agent version to use if agent doesn't specify one
 #define PCMK_DEFAULT_AGENT_VERSION "0.1"
 
 enum lsb_exitcode {
     PCMK_LSB_OK                  = 0,
+
+    // NOTE: booth (as of at least 1.1) uses this value
     PCMK_LSB_UNKNOWN_ERROR       = 1,
+
     PCMK_LSB_INVALID_PARAM       = 2,
     PCMK_LSB_UNIMPLEMENT_FEATURE = 3,
     PCMK_LSB_INSUFFICIENT_PRIV   = 4,
     PCMK_LSB_NOT_INSTALLED       = 5,
     PCMK_LSB_NOT_CONFIGURED      = 6,
     PCMK_LSB_NOT_RUNNING         = 7,
 };
 
 // LSB uses different return codes for status actions
 enum lsb_status_exitcode {
     PCMK_LSB_STATUS_OK             = 0,
     PCMK_LSB_STATUS_VAR_PID        = 1,
     PCMK_LSB_STATUS_VAR_LOCK       = 2,
     PCMK_LSB_STATUS_NOT_RUNNING    = 3,
     PCMK_LSB_STATUS_UNKNOWN        = 4,
 
     /* custom codes should be in the 150-199 range reserved for application use */
     PCMK_LSB_STATUS_NOT_INSTALLED      = 150,
     PCMK_LSB_STATUS_INSUFFICIENT_PRIV  = 151,
 };
 
 //!@{
 //! \deprecated Do not use
 
 enum nagios_exitcode {
     NAGIOS_STATE_OK        = 0,
     NAGIOS_STATE_WARNING   = 1,
     NAGIOS_STATE_CRITICAL  = 2,
     NAGIOS_STATE_UNKNOWN   = 3,
 
     /* This is a custom Pacemaker value (not a nagios convention), used as an
      * intermediate value between the services library and the executor, so the
      * executor can map it to the corresponding OCF code.
      */
     NAGIOS_INSUFFICIENT_PRIV = 100,
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
     NAGIOS_STATE_DEPENDENT   = 4,
     NAGIOS_NOT_INSTALLED     = 101,
 #endif
 };
 
 //!@}
 
 enum svc_action_flags {
     /* On timeout, only kill pid, do not kill entire pid group */
     SVC_ACTION_LEAVE_GROUP = 0x01,
     SVC_ACTION_NON_BLOCKED = 0x02,
 };
 
 typedef struct svc_action_private_s svc_action_private_t;
 
 /*!
  * \brief Object for executing external actions
  *
  * \note This object should never be instantiated directly, but instead created
  *       using one of the constructor functions (resources_action_create() for
  *       resource agents, services_alert_create() for alert agents, or
  *       services_action_create_generic() for generic executables). Similarly,
  *       do not use sizeof() on this struct.
  */
 /*
  * NOTE: Internally, services__create_resource_action() is preferable to
  * resources_action_create().
  */
 typedef struct svc_action_s {
     /*! Operation key (<resource>_<action>_<interval>) for resource actions,
      *  XML ID for alert actions, or NULL for generic actions
      */
     char *id;
 
     //! XML ID of resource being executed for resource actions, otherwise NULL
     char *rsc;
 
     //! Name of action being executed for resource actions, otherwise NULL
     char *action;
 
     //! Action interval for recurring resource actions, otherwise 0
     guint interval_ms;
 
     //! Resource standard for resource actions, otherwise NULL
     char *standard;
 
     //! Resource provider for resource actions that require it, otherwise NULL
     char *provider;
 
     //! Resource agent name for resource actions, otherwise NULL
     char *agent;
 
     int timeout;    //!< Action timeout (in milliseconds)
 
     /*! A hash table of name/value pairs to use as parameters for resource and
      *  alert actions, otherwise NULL. These will be used to set environment
      *  variables for non-fencing resource agents and alert agents, and to send
      *  stdin to fence agents.
      */
     GHashTable *params;
 
     int rc;         //!< Exit status of action (set by library upon completion)
 
     //!@{
     //! This field should be treated as internal to Pacemaker
     int pid;        // Process ID of child
     int cancel;     // Whether this is a cancellation of a recurring action
     //!@}
 
     int status;     //!< Execution status (enum pcmk_exec_status set by library)
 
     /*! Action counter (set by library for resource actions, or by caller
      * otherwise)
      */
     int sequence;
 
     //!@{
     //! This field should be treated as internal to Pacemaker
     int expected_rc;    // Unused
     int synchronous;    // Whether execution should be synchronous (blocking)
     //!@}
 
     enum svc_action_flags flags;    //!< Flag group of enum svc_action_flags
     char *stderr_data;              //!< Action stderr (set by library)
     char *stdout_data;              //!< Action stdout (set by library)
     void *cb_data;                  //!< For caller's use (not used by library)
 
     //! This field should be treated as internal to Pacemaker
     svc_action_private_t *opaque;
 } svc_action_t;
 
 /*!
  * \brief Get a list of files or directories in a given path
  *
  * \param[in] root       Full path to a directory to read
  * \param[in] files      Return list of files if TRUE or directories if FALSE
  * \param[in] executable If TRUE and files is TRUE, only return executable files
  *
  * \return List of what was found as char * items.
  * \note The caller is responsibile for freeing the result with
  *       g_list_free_full(list, free).
  */
 GList *get_directory_list(const char *root, gboolean files,
                           gboolean executable);
 
 /*!
  * \brief Get a list of providers
  *
  * \param[in] standard  List providers of this resource agent standard
  *
  * \return List of providers as char * list items (or NULL if standard does not
  *         support providers)
  * \note The caller is responsible for freeing the result using
  *       g_list_free_full(list, free).
  */
 GList *resources_list_providers(const char *standard);
 
 /*!
  * \brief Get a list of resource agents
  *
  * \param[in] standard  List agents of this standard (or NULL for all)
  * \param[in] provider  List agents of this provider (or NULL for all)
  *
  * \return List of resource agents as char * items.
  * \note The caller is responsible for freeing the result using
  *       g_list_free_full(list, free).
  */
 GList *resources_list_agents(const char *standard, const char *provider);
 
 /*!
  * Get list of available standards
  *
  * \return List of resource standards as char * items.
  * \note The caller is responsible for freeing the result using
  *       g_list_free_full(list, free).
  */
 GList *resources_list_standards(void);
 
 /*!
  * \brief Check whether a resource agent exists on the local host
  *
  * \param[in] standard  Resource agent standard of agent to check
  * \param[in] provider  Provider of agent to check (or NULL)
  * \param[in] agent     Name of agent to check
  *
  * \return TRUE if agent exists locally, otherwise FALSE
  */
 gboolean resources_agent_exists(const char *standard, const char *provider,
                                 const char *agent);
 
 /*!
  * \brief Create a new resource action
  *
  * \param[in]     name        Name of resource that action is for
  * \param[in]     standard    Resource agent standard
  * \param[in]     provider    Resource agent provider
  * \param[in]     agent       Resource agent name
  * \param[in]     action      Name of action to create
  * \param[in]     interval_ms How often to repeat action (if 0, execute once)
  * \param[in]     timeout     Error if not complete within this time (ms)
  * \param[in,out] params      Action parameters
  * \param[in]     flags       Group of enum svc_action_flags
  *
  * \return Newly allocated action
  * \note This function assumes ownership of (and may free) \p params.
  * \note The caller is responsible for freeing the return value using
  *       services_action_free().
  */
 svc_action_t *resources_action_create(const char *name, const char *standard,
                                       const char *provider, const char *agent,
                                       const char *action, guint interval_ms,
                                       int timeout, GHashTable *params,
                                       enum svc_action_flags flags);
 
 /*!
  * \brief Reschedule a recurring action for immediate execution
  *
  * \param[in] name         Name of resource that action is for
  * \param[in] action       Action's name
  * \param[in] interval_ms  Action's interval (in milliseconds)
  *
  * \return TRUE on success, otherwise FALSE
  */
 gboolean services_action_kick(const char *name, const char *action,
                               guint interval_ms);
 
 const char *resources_find_service_class(const char *agent);
 
 /*!
  * \brief Request execution of an arbitrary command
  *
  * This API has useful infrastructure in place to be able to run a command
  * in the background and get notified via a callback when the command finishes.
  *
  * \param[in] exec  Full path to command executable
  * \param[in] args  NULL-terminated list of arguments to pass to command
  *
  * \return Newly allocated action object
  */
 svc_action_t *services_action_create_generic(const char *exec,
                                              const char *args[]);
 
 void services_action_cleanup(svc_action_t *op);
 void services_action_free(svc_action_t *op);
 int services_action_user(svc_action_t *op, const char *user);
 gboolean services_action_sync(svc_action_t *op);
 
 /*!
  * \brief Run an action asynchronously, with callback after process is forked
  *
  * \param[in,out] op                    Action to run
  * \param[in]     action_callback       Function to call when action completes
  *                                      (if NULL, any previously set callback will
  *                                      continue to be used)
  * \param[in]     action_fork_callback  Function to call after child process is
  *                                      forked for action (if NULL, any
  *                                      previously set callback will continue to
  *                                      be used)
  *
  * \retval TRUE if the caller should not free or otherwise use \p op again,
  *         because one of these conditions is true:
  *
  *         * \p op is NULL.
  *         * The action was successfully initiated, in which case
  *           \p action_fork_callback has been called, but \p action_callback has
  *           not (it will be called when the action completes).
  *         * The action's ID matched an existing recurring action. The existing
  *           action has taken over the callback and callback data from \p op
  *           and has been re-initiated asynchronously, and \p op has been freed.
  *         * Another action for the same resource is in flight, and \p op will
  *           be blocked until it completes.
  *         * The action could not be initiated, and is either non-recurring or
  *           being cancelled. \p action_fork_callback has not been called, but
  *           \p action_callback has, and \p op has been freed.
  *
  * \retval FALSE if \op is still valid, because the action cannot be initiated,
  *         and is a recurring action that is not being cancelled.
  *         \p action_fork_callback has not been called, but \p action_callback
  *         has, and a timer has been set for the next invocation of \p op.
  */
 gboolean services_action_async_fork_notify(svc_action_t *op,
         void (*action_callback) (svc_action_t *),
         void (*action_fork_callback) (svc_action_t *));
 
 /*!
  * \brief Request asynchronous execution of an action
  *
  * \param[in,out] op               Action to execute
  * \param[in]     action_callback  Function to call when the action completes
  *                                 (if NULL, any previously set callback will
  *                                 continue to be used)
  *
  * \retval TRUE if the caller should not free or otherwise use \p op again,
  *         because one of these conditions is true:
  *
  *         * \p op is NULL.
  *         * The action was successfully initiated, in which case
  *           \p action_callback has not been called (it will be called when the
  *           action completes).
  *         * The action's ID matched an existing recurring action. The existing
  *           action has taken over the callback and callback data from \p op
  *           and has been re-initiated asynchronously, and \p op has been freed.
  *         * Another action for the same resource is in flight, and \p op will
  *           be blocked until it completes.
  *         * The action could not be initiated, and is either non-recurring or
  *           being cancelled. \p action_callback has been called, and \p op has
  *           been freed.
  *
  * \retval FALSE if \op is still valid, because the action cannot be initiated,
  *         and is a recurring action that is not being cancelled.
  *         \p action_callback has been called, and a timer has been set for the
  *         next invocation of \p op.
  */
 gboolean services_action_async(svc_action_t *op,
                                void (*action_callback) (svc_action_t *));
 
 gboolean services_action_cancel(const char *name, const char *action,
                                 guint interval_ms);
 
 /* functions for alert agents */
 svc_action_t *services_alert_create(const char *id, const char *exec,
                                    int timeout, GHashTable *params,
                                    int sequence, void *cb_data);
 gboolean services_alert_async(svc_action_t *action,
                               void (*cb)(svc_action_t *op));
 
 enum ocf_exitcode services_result2ocf(const char *standard, const char *action,
                                       int exit_status);
 
     static inline const char *services_ocf_exitcode_str(enum ocf_exitcode code) {
         switch (code) {
             case PCMK_OCF_OK:
                 return "ok";
             case PCMK_OCF_UNKNOWN_ERROR:
                 return "error";
             case PCMK_OCF_INVALID_PARAM:
                 return "invalid parameter";
             case PCMK_OCF_UNIMPLEMENT_FEATURE:
                 return "unimplemented feature";
             case PCMK_OCF_INSUFFICIENT_PRIV:
                 return "insufficient privileges";
             case PCMK_OCF_NOT_INSTALLED:
                 return "not installed";
             case PCMK_OCF_NOT_CONFIGURED:
                 return "not configured";
             case PCMK_OCF_NOT_RUNNING:
                 return "not running";
             case PCMK_OCF_RUNNING_PROMOTED:
                 return "promoted";
             case PCMK_OCF_FAILED_PROMOTED:
                 return "promoted (failed)";
             case PCMK_OCF_DEGRADED:
                 return "OCF_DEGRADED";
             case PCMK_OCF_DEGRADED_PROMOTED:
                 return "promoted (degraded)";
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
             case PCMK_OCF_NOT_SUPPORTED:
                 return "not supported (DEPRECATED STATUS)";
             case PCMK_OCF_CANCELLED:
                 return "cancelled (DEPRECATED STATUS)";
             case PCMK_OCF_OTHER_ERROR:
                 return "other error (DEPRECATED STATUS)";
             case PCMK_OCF_SIGNAL:
                 return "interrupted by signal (DEPRECATED STATUS)";
             case PCMK_OCF_PENDING:
                 return "pending (DEPRECATED STATUS)";
             case PCMK_OCF_TIMEOUT:
                 return "timeout (DEPRECATED STATUS)";
 #endif
             default:
                 return "unknown";
         }
     }
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 #include <crm/services_compat.h>
 #endif
 
 #  ifdef __cplusplus
 }
 #  endif
 
 #endif                          /* __PCMK_SERVICES__ */
diff --git a/include/crm/stonith-ng.h b/include/crm/stonith-ng.h
index 6d58f29a94..9bff891381 100644
--- a/include/crm/stonith-ng.h
+++ b/include/crm/stonith-ng.h
@@ -1,702 +1,704 @@
 /*
  * Copyright 2004-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_STONITH_NG__H
 #  define PCMK__CRM_STONITH_NG__H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
  * \file
  * \brief Fencing aka. STONITH
  * \ingroup fencing
  */
 
 /* IMPORTANT: DLM source code includes this file directly, without having access
  * to other Pacemaker headers on its include path, so this file should *not*
  * include any other Pacemaker headers. (DLM might be updated to avoid the
  * issue, but we should still follow this guideline for a long time after.)
  */
 
 #  include <dlfcn.h>
 #  include <errno.h>
 #  include <stdbool.h>  // bool
 #  include <stdint.h>   // uint32_t
 #  include <time.h>     // time_t
 
 /* *INDENT-OFF* */
 enum stonith_state {
     stonith_connected_command,
     stonith_connected_query,
     stonith_disconnected,
 };
 
 enum stonith_call_options {
     st_opt_none            = 0x00000000,
     st_opt_verbose         = 0x00000001,
     st_opt_allow_suicide   = 0x00000002,
 
     st_opt_manual_ack      = 0x00000008,
     st_opt_discard_reply   = 0x00000010,
 /*    st_opt_all_replies     = 0x00000020, */
     st_opt_topology        = 0x00000040,
     st_opt_scope_local     = 0x00000100,
     st_opt_cs_nodeid       = 0x00000200,
     st_opt_sync_call       = 0x00001000,
     /*! Allow the timeout period for a callback to be adjusted
      *  based on the time the server reports the operation will take. */
     st_opt_timeout_updates = 0x00002000,
     /*! Only report back if operation is a success in callback */
     st_opt_report_only_success = 0x00004000,
     /* used where ever apropriate - e.g. cleanup of history */
     st_opt_cleanup         = 0x000080000,
     /* used where ever apropriate - e.g. send out a history query to all nodes */
     st_opt_broadcast       = 0x000100000,
 };
 
 /*! Order matters here, do not change values */
 enum op_state
 {
     st_query,
     st_exec,
     st_done,
     st_duplicate,
     st_failed,
 };
 
 // Supported fence agent interface standards
 enum stonith_namespace {
     st_namespace_invalid,
     st_namespace_any,
     st_namespace_internal,  // Implemented internally by Pacemaker
 
     /* Neither of these projects are active any longer, but the fence agent
      * interfaces they created are still in use and supported by Pacemaker.
      */
     st_namespace_rhcs,      // Red Hat Cluster Suite compatible
     st_namespace_lha,       // Linux-HA compatible
 };
 
 enum stonith_namespace stonith_text2namespace(const char *namespace_s);
 const char *stonith_namespace2text(enum stonith_namespace st_namespace);
 enum stonith_namespace stonith_get_namespace(const char *agent,
                                              const char *namespace_s);
 
 typedef struct stonith_key_value_s {
     char *key;
     char *value;
         struct stonith_key_value_s *next;
 } stonith_key_value_t;
 
 typedef struct stonith_history_s {
     char *target;
     char *action;
     char *origin;
     char *delegate;
     char *client;
     int state;
     time_t completed;
     struct stonith_history_s *next;
     long completed_nsec;
     char *exit_reason;
 } stonith_history_t;
 
 typedef struct stonith_s stonith_t;
 
 typedef struct stonith_event_s
 {
     char *id;
     char *type;     //!< \deprecated Will be removed in future release
     char *message;  //!< \deprecated Will be removed in future release
     char *operation;
 
     int result;
     char *origin;
     char *target;
     char *action;
     char *executioner;
 
     char *device;
 
     /*! The name of the client that initiated the action. */
     char *client_origin;
 
     //! \internal This field should be treated as internal to Pacemaker
     void *opaque;
 } stonith_event_t;
 
 typedef struct stonith_callback_data_s {
     int rc;
     int call_id;
     void *userdata;
 
     //! \internal This field should be treated as internal to Pacemaker
     void *opaque;
 } stonith_callback_data_t;
 
 typedef struct stonith_api_operations_s
 {
     /*!
      * \brief Destroy a fencer connection
      *
      * \param[in,out] st  Fencer connection to destroy
      */
     int (*free) (stonith_t *st);
 
     /*!
      * \brief Connect to the local fencer
      *
      * \param[in,out] st          Fencer connection to connect
      * \param[in]     name        Client name to use
      * \param[out]    stonith_fd  If NULL, use a main loop, otherwise
      *                            store IPC file descriptor here
      *
      * \return Legacy Pacemaker return code
      */
     int (*connect) (stonith_t *st, const char *name, int *stonith_fd);
 
     /*!
      * \brief Disconnect from the local stonith daemon.
      *
      * \param[in,out] st  Fencer connection to disconnect
      *
      * \return Legacy Pacemaker return code
      */
     int (*disconnect)(stonith_t *st);
 
     /*!
      * \brief Unregister a fence device with the local fencer
      *
      * \param[in,out] st       Fencer connection to disconnect
      * \param[in]     options  Group of enum stonith_call_options
      * \param[in]     name     ID of fence device to unregister
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*remove_device)(stonith_t *st, int options, const char *name);
 
     /*!
      * \brief Register a fence device with the local fencer
      *
      * \param[in,out] st           Fencer connection to use
      * \param[in]     options      Group of enum stonith_call_options
      * \param[in]     id           ID of fence device to register
      * \param[in]     namespace_s  Type of fence agent to search for ("redhat"
      *                             or "stonith-ng" for RHCS-style, "internal"
      *                             for Pacemaker-internal devices, "heartbeat"
      *                             for LHA-style, or "any" or NULL for any)
      * \param[in]     agent        Name of fence agent for device
      * \param[in]     params       Fence agent parameters for device
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*register_device)(stonith_t *st, int options, const char *id,
                            const char *namespace_s, const char *agent,
                            const stonith_key_value_t *params);
 
     /*!
      * \brief Unregister a fencing level for specified node with local fencer
      *
      * \param[in,out] st       Fencer connection to use
      * \param[in]     options  Group of enum stonith_call_options
      * \param[in]     node     Target node to unregister level for
      * \param[in]     level    Topology level number to unregister
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*remove_level)(stonith_t *st, int options, const char *node,
                         int level);
 
     /*!
      * \brief Register a fencing level for specified node with local fencer
      *
      * \param[in,out] st           Fencer connection to use
      * \param[in]     options      Group of enum stonith_call_options
      * \param[in]     node         Target node to register level for
      * \param[in]     level        Topology level number to register
      * \param[in]     device_list  Devices to register in level
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*register_level)(stonith_t *st, int options, const char *node,
                           int level, const stonith_key_value_t *device_list);
 
     /*!
      * \brief Retrieve a fence agent's metadata
      *
      * \param[in,out] stonith       Fencer connection
      * \param[in]     call_options  Group of enum stonith_call_options
      *                              (currently ignored)
      * \param[in]     agent         Fence agent to query
      * \param[in]     namespace_s   Type of fence agent to search for ("redhat"
      *                              or "stonith-ng" for RHCS-style, "internal"
      *                              for Pacemaker-internal devices, "heartbeat"
      *                              for LHA-style, or "any" or NULL for any)
      * \param[out]    output        Where to store metadata
      * \param[in]     timeout_sec   Error if not complete within this time
      *
      * \return Legacy Pacemaker return code
      * \note The caller is responsible for freeing *output using free().
      */
     int (*metadata)(stonith_t *stonith, int call_options, const char *agent,
                     const char *namespace_s, char **output, int timeout_sec);
 
     /*!
      * \brief Retrieve a list of installed fence agents
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      *                              (currently ignored)
      * \param[in]     namespace_s   Type of fence agents to list ("redhat"
      *                              or "stonith-ng" for RHCS-style, "internal" for
      *                              Pacemaker-internal devices, "heartbeat" for
      *                              LHA-style, or "any" or NULL for all)
      * \param[out]    devices       Where to store agent list
      * \param[in]     timeout       Error if unable to complete within this
      *                              (currently ignored)
      *
      * \return Number of items in list on success, or negative errno otherwise
      * \note The caller is responsible for freeing the returned list with
      *       stonith_key_value_freeall().
      */
     int (*list_agents)(stonith_t *stonith, int call_options,
                        const char *namespace_s, stonith_key_value_t **devices,
                        int timeout);
 
     /*!
      * \brief Get the output of a fence device's list action
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     id            Fence device ID to run list for
      * \param[out]    list_info     Where to store list output
      * \param[in]     timeout       Error if unable to complete within this
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*list)(stonith_t *stonith, int call_options, const char *id,
                 char **list_info, int timeout);
 
     /*!
      * \brief Check whether a fence device is reachable by monitor action
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     id            Fence device ID to run monitor for
      * \param[in]     timeout       Error if unable to complete within this
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*monitor)(stonith_t *stonith, int call_options, const char *id,
                    int timeout);
 
     /*!
      * \brief Check whether a fence device target is reachable by status action
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     id            Fence device ID to run status for
      * \param[in]     port          Fence target to run status for
      * \param[in]     timeout       Error if unable to complete within this
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*status)(stonith_t *stonith, int call_options, const char *id,
                   const char *port, int timeout);
 
     /*!
      * \brief List registered fence devices
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     target        Fence target to run status for
      * \param[out]    devices       Where to store list of fence devices
      * \param[in]     timeout       Error if unable to complete within this
      *
      * \note If node is provided, only devices that can fence the node id
      *       will be returned.
      *
      * \return Number of items in list on success, or negative errno otherwise
      */
     int (*query)(stonith_t *stonith, int call_options, const char *target,
                  stonith_key_value_t **devices, int timeout);
 
     /*!
      * \brief Request that a target get fenced
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     node          Fence target
      * \param[in]     action        "on", "off", or "reboot"
      * \param[in]     timeout       Default per-device timeout to use with
      *                              each executed device
      * \param[in]     tolerance     Accept result of identical fence action
      *                              completed within this time
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*fence)(stonith_t *stonith, int call_options, const char *node,
                  const char *action, int timeout, int tolerance);
 
     /*!
      * \brief Manually confirm that a node has been fenced
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     target        Fence target
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*confirm)(stonith_t *stonith, int call_options, const char *target);
 
     /*!
      * \brief List fencing actions that have occurred for a target
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     node          Fence target
      * \param[out]    history       Where to store list of fencing actions
      * \param[in]     timeout       Error if unable to complete within this
      *
      * \return Legacy Pacemaker return code
      */
     int (*history)(stonith_t *stonith, int call_options, const char *node,
                    stonith_history_t **history, int timeout);
 
     /*!
      * \brief Register a callback for fence notifications
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     event         Event to register for
      * \param[in]     callback      Callback to register
      *
      * \return Legacy Pacemaker return code
      */
     int (*register_notification)(stonith_t *stonith, const char *event,
                                  void (*callback)(stonith_t *st,
                                                   stonith_event_t *e));
 
     /*!
      * \brief Unregister callbacks for fence notifications
      *
      * \param[in,out] stonith  Fencer connection to use
      * \param[in]     event    Event to unregister callbacks for (NULL for all)
      *
      * \return Legacy Pacemaker return code
      */
     int (*remove_notification)(stonith_t *stonith, const char *event);
 
     /*!
      * \brief Register a callback for an asynchronous fencing result
      *
      * \param[in,out] stonith        Fencer connection to use
      * \param[in]     call_id        Call ID to register callback for
      * \param[in]     timeout        Error if result not received in this time
      * \param[in]     options        Group of enum stonith_call_options
      *                               (respects \c st_opt_timeout_updates and
      *                               \c st_opt_report_only_success)
      * \param[in,out] user_data      Pointer to pass to callback
      * \param[in]     callback_name  Unique identifier for callback
      * \param[in]     callback       Callback to register (may be called
      *                               immediately if \p call_id indicates error)
      *
      * \return \c TRUE on success, \c FALSE if call_id indicates error,
      *         or -EINVAL if \p stonith is not valid
      */
     int (*register_callback)(stonith_t *stonith, int call_id, int timeout,
                              int options, void *user_data,
                              const char *callback_name,
                              void (*callback)(stonith_t *st,
                                               stonith_callback_data_t *data));
 
     /*!
      * \brief Unregister callbacks for asynchronous fencing results
      *
      * \param[in,out] stonith        Fencer connection to use
      * \param[in]     call_id        If \p all_callbacks is false, call ID
      *                               to unregister callback for
      * \param[in]     all_callbacks  If true, unregister all callbacks
      *
      * \return pcmk_ok
      */
     int (*remove_callback)(stonith_t *stonith, int call_id, bool all_callbacks);
 
     /*!
      * \brief Unregister fencing level for specified node, pattern or attribute
      *
      * \param[in,out] st       Fencer connection to use
      * \param[in]     options  Group of enum stonith_call_options
      * \param[in]     node     If not NULL, unregister level targeting this node
      * \param[in]     pattern  If not NULL, unregister level targeting nodes
      *                         whose names match this regular expression
      * \param[in]     attr     If this and \p value are not NULL, unregister
      *                         level targeting nodes with this node attribute
      *                         set to \p value
      * \param[in]     value    If this and \p attr are not NULL, unregister
      *                         level targeting nodes with node attribute \p attr
      *                         set to this
      * \param[in]     level    Topology level number to remove
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      * \note The caller should set only one of \p node, \p pattern, or \p attr
      *       and \p value.
      */
     int (*remove_level_full)(stonith_t *st, int options,
                              const char *node, const char *pattern,
                              const char *attr, const char *value, int level);
 
     /*!
      * \brief Register fencing level for specified node, pattern or attribute
      *
      * \param[in,out] st           Fencer connection to use
      * \param[in]     options      Group of enum stonith_call_options
      * \param[in]     node         If not NULL, register level targeting this
      *                             node by name
      * \param[in]     pattern      If not NULL, register level targeting nodes
      *                             whose names match this regular expression
      * \param[in]     attr         If this and \p value are not NULL, register
      *                             level targeting nodes with this node
      *                             attribute set to \p value
      * \param[in]     value        If this and \p attr are not NULL, register
      *                             level targeting nodes with node attribute
      *                             \p attr set to this
      * \param[in]     level        Topology level number to remove
      * \param[in]     device_list  Devices to use in level
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      *
      * \note The caller should set only one of node, pattern or attr/value.
      */
     int (*register_level_full)(stonith_t *st, int options,
                                const char *node, const char *pattern,
                                const char *attr, const char *value, int level,
                                const stonith_key_value_t *device_list);
 
     /*!
      * \brief Validate an arbitrary stonith device configuration
      *
      * \param[in,out] st            Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     rsc_id        ID used to replace CIB secrets in \p params
      * \param[in]     namespace_s   Type of fence agent to validate ("redhat"
      *                              or "stonith-ng" for RHCS-style, "internal"
      *                              for Pacemaker-internal devices, "heartbeat"
      *                              for LHA-style, or "any" or NULL for any)
      * \param[in]     agent         Fence agent to validate
      * \param[in]     params        Configuration parameters to pass to agent
      * \param[in]     timeout       Fail if no response within this many seconds
      * \param[out]    output        If non-NULL, where to store any agent output
      * \param[out]    error_output  If non-NULL, where to store agent error output
      *
      * \return pcmk_ok if validation succeeds, -errno otherwise
      * \note If pcmk_ok is returned, the caller is responsible for freeing
      *       the output (if requested) with free().
      */
     int (*validate)(stonith_t *st, int call_options, const char *rsc_id,
                     const char *namespace_s, const char *agent,
                     const stonith_key_value_t *params, int timeout,
                     char **output, char **error_output);
 
     /*!
      * \brief Request delayed fencing of a target
      *
      * \param[in,out] stonith       Fencer connection to use
      * \param[in]     call_options  Group of enum stonith_call_options
      * \param[in]     node          Fence target
      * \param[in]     action        "on", "off", or "reboot"
      * \param[in]     timeout       Default per-device timeout to use with
      *                              each executed device
      * \param[in]     tolerance     Accept result of identical fence action
      *                              completed within this time
      * \param[in]     delay         Execute fencing after this delay (-1
      *                              disables any delay from pcmk_delay_base
      *                              and pcmk_delay_max)
      *
      * \return pcmk_ok (if synchronous) or positive call ID (if asynchronous)
      *         on success, otherwise a negative legacy Pacemaker return code
      */
     int (*fence_with_delay)(stonith_t *stonith, int call_options,
                             const char *node, const char *action, int timeout,
                             int tolerance, int delay);
 
 } stonith_api_operations_t;
 
 struct stonith_s
 {
     enum stonith_state state;
 
     int call_id;
     int call_timeout;   //!< \deprecated Unused
     void *st_private;
 
     stonith_api_operations_t *cmds;
 };
 /* *INDENT-ON* */
 
 /* Core functions */
 stonith_t *stonith_api_new(void);
 void stonith_api_delete(stonith_t * st);
 
 void stonith_dump_pending_callbacks(stonith_t * st);
 
 bool stonith_dispatch(stonith_t * st);
 
 stonith_key_value_t *stonith_key_value_add(stonith_key_value_t * kvp, const char *key,
                                            const char *value);
 void stonith_key_value_freeall(stonith_key_value_t * kvp, int keys, int values);
 
 void stonith_history_free(stonith_history_t *history);
 
 // Convenience functions
 int stonith_api_connect_retry(stonith_t *st, const char *name,
                               int max_attempts);
 const char *stonith_op_state_str(enum op_state state);
 
 /* Basic helpers that allows nodes to be fenced and the history to be
  * queried without mainloop or the caller understanding the full API
  *
  * At least one of nodeid and uname are required
+ *
+ * NOTE: DLM uses both of these
  */
 int stonith_api_kick(uint32_t nodeid, const char *uname, int timeout, bool off);
 time_t stonith_api_time(uint32_t nodeid, const char *uname, bool in_progress);
 
 /*
  * Helpers for using the above functions without install-time dependencies
  *
  * Usage:
  *  #include <crm/stonith-ng.h>
  *
  * To turn a node off by corosync nodeid:
  *  stonith_api_kick_helper(nodeid, 120, 1);
  *
  * To check the last fence date/time (also by nodeid):
  *  last = stonith_api_time_helper(nodeid, 0);
  *
  * To check if fencing is in progress:
  *  if(stonith_api_time_helper(nodeid, 1) > 0) { ... }
  *
  * eg.
 
  #include <stdio.h>
  #include <time.h>
  #include <crm/stonith-ng.h>
  int
  main(int argc, char ** argv)
  {
      int rc = 0;
      int nodeid = 102;
 
      rc = stonith_api_time_helper(nodeid, 0);
      printf("%d last fenced at %s\n", nodeid, ctime(rc));
 
      rc = stonith_api_kick_helper(nodeid, 120, 1);
      printf("%d fence result: %d\n", nodeid, rc);
 
      rc = stonith_api_time_helper(nodeid, 0);
      printf("%d last fenced at %s\n", nodeid, ctime(rc));
 
      return 0;
  }
 
  */
 
 #  define STONITH_LIBRARY "libstonithd.so.26"
 
 typedef int (*st_api_kick_fn) (int nodeid, const char *uname, int timeout, bool off);
 typedef time_t (*st_api_time_fn) (int nodeid, const char *uname, bool in_progress);
 
 static inline int
 stonith_api_kick_helper(uint32_t nodeid, int timeout, bool off)
 {
     static void *st_library = NULL;
     static st_api_kick_fn st_kick_fn;
 
     if (st_library == NULL) {
         st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY);
     }
     if (st_library && st_kick_fn == NULL) {
         st_kick_fn = (st_api_kick_fn) dlsym(st_library, "stonith_api_kick");
     }
     if (st_kick_fn == NULL) {
 #ifdef ELIBACC
         return -ELIBACC;
 #else
         return -ENOSYS;
 #endif
     }
 
     return (*st_kick_fn) (nodeid, NULL, timeout, off);
 }
 
 static inline time_t
 stonith_api_time_helper(uint32_t nodeid, bool in_progress)
 {
     static void *st_library = NULL;
     static st_api_time_fn st_time_fn;
 
     if (st_library == NULL) {
         st_library = dlopen(STONITH_LIBRARY, RTLD_LAZY);
     }
     if (st_library && st_time_fn == NULL) {
         st_time_fn = (st_api_time_fn) dlsym(st_library, "stonith_api_time");
     }
     if (st_time_fn == NULL) {
         return 0;
     }
 
     return (*st_time_fn) (nodeid, NULL, in_progress);
 }
 
 /**
  * Does the given agent describe a stonith resource that can exist?
  *
  * \param[in] agent     What is the name of the agent?
  * \param[in] timeout   Timeout to use when querying.  If 0 is given,
  *                      use a default of 120.
  *
  * \return A boolean
  */
 bool stonith_agent_exists(const char *agent, int timeout);
 
 /*!
  * \brief Turn fence action into a more readable string
  *
  * \param[in] action  Fence action
  */
 const char *stonith_action_str(const char *action);
 
 #if !defined(PCMK_ALLOW_DEPRECATED) || (PCMK_ALLOW_DEPRECATED == 1)
 /* Normally we'd put this section in a separate file (crm/fencing/compat.h), but
  * we can't do that for the reason noted at the top of this file. That does mean
  * we have to duplicate these declarations where they're implemented.
  */
 
 //! \deprecated Use stonith_get_namespace() instead
 const char *get_stonith_provider(const char *agent, const char *provider);
 
 #endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
diff --git a/include/crm_config.h.in b/include/crm_config.h.in
index 9095ba2301..a7ec62eaae 100644
--- a/include/crm_config.h.in
+++ b/include/crm_config.h.in
@@ -1,76 +1,78 @@
 /*
  * Copyright 2006-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU General Public License version 2
  * or later (GPLv2+) WITHOUT ANY WARRANTY.
  */
 
 #ifndef PCMK__CRM_CONFIG__H
 #define PCMK__CRM_CONFIG__H
 
 /****** Versions ******/
 
 /* Current pacemaker version */
 #undef PACEMAKER_VERSION
 
 /* Build version */
 #undef BUILD_VERSION
 
 /****** Other ******/
 
 /* Group to run Pacemaker daemons as */
 #undef CRM_DAEMON_GROUP
 
 /* User to run Pacemaker daemons as */
 #undef CRM_DAEMON_USER
 
 /****** Directories ******/
 
 /* Where Pacemaker can store log files */
 #undef CRM_LOG_DIR
 
 /* Location for Pacemaker daemons */
 #undef CRM_DAEMON_DIR
 
 /* Where to keep blackbox dumps */
 #undef CRM_BLACKBOX_DIR
 
 /* Where to keep configuration files */
 #undef CRM_CONFIG_DIR
 
 /* Where to keep scheduler outputs */
 #undef PE_STATE_DIR
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /* Location to store core files produced by Pacemaker daemons */
 #undef CRM_CORE_DIR
 
 /* Where to keep state files and sockets */
 #undef CRM_STATE_DIR
 
 /* Location for the Pacemaker Relax-NG Schema */
 #undef CRM_SCHEMA_DIRECTORY
 
 /* Where to keep configuration files like authkey */
 #undef PACEMAKER_CONFIG_DIR
 
 /* Where OCF resource agents and libraries can be found */
 #undef OCF_ROOT_DIR
 
 /****** Features ******/
 
 /* Set of enabled features */
 #undef CRM_FEATURES
 
+// NOTE: sbd (as of at least 1.5.2) uses this
 /* Support the Corosync messaging and membership layer */
 #undef SUPPORT_COROSYNC
 
 /* Support systemd based system services */
 #undef SUPPORT_SYSTEMD
 
 /* Support upstart based system services */
 //! \deprecated Do not use (always treat as 0)
 #undef SUPPORT_UPSTART
 
 #endif /* CRM_CONFIG__H */