diff --git a/text/0015-Service-Reference-Retrieval.md b/text/0015-Service-Reference-Retrieval.md
new file mode 100644
index 0000000..fcbf68d
--- /dev/null
+++ b/text/0015-Service-Reference-Retrieval.md
@@ -0,0 +1,231 @@
+- Start Date: 2024-10-10
+- CppMicroServices PR: https://github.com/CppMicroServices/CppMicroServices/pull/1044
+
+# Add an free API in that can retrieve a ServiceReference
from a std::shared_ptr\
given to the client by the framework
+
+## Summary
+
+Currently there is no API in the cppmicroservices
namespace that can retrieve a ServiceReference
from the std::shared_ptr\
itself.
+This document discusses need for such API in the particular use case of declarative services (DS) and its possible design/solution.
+
+## Motivation
+
+Developers using DS rely on DS's SCR (service component runtime) to inject services statically at construction or dynamically using the bind
and unbind
methods. These std::shared_ptr\
s can then be used by the client. However, clients often use properties in the Service to store metadata relevant to that service. Those properties, however, are not available to the std::shared_ptr\
itself, only via its ServiceReference
.
+
+Given this it seems appropriate to have a new method that the client can use to translate a std::shared_ptr\
into its ServiceReference
.
+
+## Requirements
+
+This API must:
+
+1. take in a ServiceObject\
and return the ServiceReference\
for that service where T
is any class interface
+2. not expose internal implementation details to the user
+
+## Detailed design
+
+ServiceReferenceFromService
API will be declared in the file framework/include/cppmicroservices/ServiceReference.h in the namespace cppmicroservices::
as below:
+
+```c++
+
+/**
+* \ingroup MicroServices
+* \ingroup gr_servicereference
+*
+* A method to retrieve a ServiceObject
's original ServiceReference
+*
+*/
+US_Framework_EXPORT ServiceReferenceU ServiceReferenceFromService(std::shared_ptr const& s);
+
+/**
+* \ingroup MicroServices
+* \ingroup gr_servicereference
+*
+* A method to retrieve a ServiceObject
's original ServiceReference
+*
+* @tparam T The class type of the ServiceObject
+* @tparam U The class type of the ServiceReference
. Defaults to T
if not specified.
+*/
+template
+ServiceReference
+ServiceReferenceFromService(std::shared_ptr const& s)
+{
+ return ServiceReference(ServiceReferenceFromService(std::static_pointer_cast(s)));
+}
+
+```
+
+This API will take the std::shared_ptr\
and first verify that it was a std::shared_ptr\
created by the CppMicroServices framework.
+
+If it is valid, it will return the original ServiceReference
for that std::shared_ptr\
.
+
+A typical usage workflow could be as below, in the static constructor of a service ServiceImpl
which depends on a service of type ServiceInterface2
.
+
+```c++
+ServiceImpl::ServiceImpl(std::shared_ptr const& dep) {
+ // get the reference
+ ServiceReference depRef = cppmicroservices::ServiceReferenceFromService(dep);
+ // get a property from the ServiceReference's metadata
+ auto someProp = cppmicroservices::any_cast(retSRef.GetProperty("someProp"));
+ // use that property
+ doSomethingWith(someProp);
+}
+
+```
+
+## Implementation
+
+In order to solve this problem, we have to somehow embed metadata into the std::shared_ptr\
about its ServiceReference
in a way that is inaccessible directly by clients.
+
+One solution that we have found is to embed a custom deleter into the std::shared_ptr\
and retrieve that using the std::get_deleter
functionality.
+
+The objects that would allow this can be seen below:
+
+```c++
+
+/* @brief Private helper struct used to facilitate the shared_ptr aliasing constructor
+ * in BundleContext::GetService method. The aliasing constructor helps automate
+ * the call to UngetService method.
+ *
+ * Service consumers can simply call GetService to obtain a shared_ptr to the
+ * service object and not worry about calling UngetService when they are done.
+ * The UngetService is called when all instances of the returned shared_ptr object
+ * go out of scope.
+ */
+template
+struct ServiceHolder
+{
+ bool singletonService;
+ std::weak_ptr const b;
+ ServiceReferenceBase const sref;
+ std::shared_ptr const service;
+ InterfaceMapConstPtr const interfaceMap;
+
+ ServiceHolder(ServiceHolder&) = default;
+ ServiceHolder(ServiceHolder&&) noexcept = default;
+ ServiceHolder& operator=(ServiceHolder&) = delete;
+ ServiceHolder& operator=(ServiceHolder&&) noexcept = delete;
+
+ ServiceHolder(std::shared_ptr const& b,
+ ServiceReferenceBase const& sr,
+ std::shared_ptr s,
+ InterfaceMapConstPtr im)
+ : singletonService(s ? true : false)
+ , b(b)
+ , sref(sr)
+ , service(std::move(s))
+ , interfaceMap(std::move(im))
+ {
+ }
+
+ ~ServiceHolder()
+ {
+ try
+ {
+ singletonService ? destroySingleton() : destroyPrototype();
+ }
+ catch (...)
+ {
+ // Make sure that we don't crash if the shared_ptr service object outlives
+ // the BundlePrivate or CoreBundleContext objects.
+ if (!b.expired())
+ {
+ DIAG_LOG(*b.lock()->coreCtx->sink)
+ << "UngetService threw an exception. " << util::GetLastExceptionStr();
+ }
+ // don't throw exceptions from the destructor. For an explanation, see:
+ // https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md
+ // Following this rule means that a FrameworkEvent isn't an option here
+ // since it contains an exception object which clients could throw.
+ }
+ }
+
+ private:
+ void
+ destroySingleton()
+ {
+ sref.d.Load()->UngetService(b.lock(), true);
+ }
+
+ void
+ destroyPrototype()
+ {
+ auto bundle = b.lock();
+ if (sref)
+ {
+ bool isPrototypeScope
+ = sref.GetProperty(Constants::SERVICE_SCOPE).ToString() == Constants::SCOPE_PROTOTYPE;
+
+ if (isPrototypeScope)
+ {
+ sref.d.Load()->UngetPrototypeService(bundle, interfaceMap);
+ }
+ else
+ {
+ sref.d.Load()->UngetService(bundle, true);
+ }
+ }
+ }
+};
+
+/* @brief Private helper struct used to facilitate the retrieval of a serviceReference from
+ * a serviceObject.
+ *
+ * Service consumers can pass a service to the public API ServiceReferenceFromService.
+ * This method can use the std::get_deleter method to retrieve this object and through
+ * it the original serviceReference.
+ */
+class CustomServiceDeleter
+{
+ public:
+ CustomServiceDeleter(ServiceHolder* sh) : sHolder(sh) {}
+
+ void
+ operator()(ServiceHolder* sh)
+ {
+ delete sh;
+ }
+
+ [[nodiscard]] ServiceReferenceBase
+ getServiceRef() const
+ {
+ return sHolder->sref;
+ }
+
+ private:
+ ServiceHolder const* const sHolder;
+};
+
+ServiceReferenceU
+ServiceReferenceFromService(std::shared_ptr const& s)
+{
+ auto deleter = std::get_deleter(s);
+ if (!deleter)
+ {
+ throw std::runtime_error("The input is not a CppMicroServices managed ServiceObject");
+ }
+ return deleter->getServiceRef();
+}
+```
+
+The new way that ServiceHolder
objects would be constructed can be seen below:
+
+```c++
+// For a Singleton object (from framework/src/Bundle/BundleContext.cpp)
+auto serviceHolder = new ServiceHolder(b, reference, reference.d.Load()->GetService(b.get()), nullptr);
+std::shared_ptr> h(serviceHolder, CustomServiceDeleter { serviceHolder });
+return std::shared_ptr(h, h->service.get());
+
+// For a prototype object (from framework/src/service/ServiceObjects.cpp)
+auto sh = new ServiceHolder { bundle_, d->m_reference, nullptr, result };
+std::shared_ptr> h(sh, CustomServiceDeleter { sh });
+return InterfaceMapConstPtr(h, h->interfaceMap.get());
+```
+
+## How we teach this
+
+If the proposal is accepted, the CppMicroServices doxygen guide will be modified to reflect the new functionality.
+Most clients will not need this functionality. Configurations can be injected into DS services using ConfigAdmin.
+
+## Drawbacks
+
+- We are using custom deleters in a way that they were not intended to be used.