diff --git a/docs/design/cpp_abstraction_layer_api_for_user_applications.md b/docs/design/cpp_abstraction_layer_api_for_user_applications.md
new file mode 100644
index 0000000..ba1d685
--- /dev/null
+++ b/docs/design/cpp_abstraction_layer_api_for_user_applications.md
@@ -0,0 +1,297 @@
+# C++ Diagnostic API Layer - Application Usage
+
+This API layer provides application-facing abstractions for UDS and SOVD diagnostics.
+Applications implement service/resource/operation interfaces and register them via builder classes.
+The resulting `DiagnosticServicesCollection` controls lifetime and hence keeps the implemented application
+functionality connected to the underlying binding.
+
+## Design Goals
+
+ - This API Layer acts as abstraction layer between user code and a concrete binding implementation which communicates with the SOVD Server.
+ - guarantees clear independence from underlying implementation details and thus, facilitates easy unit-testability of user code
+ - concrete implementation of the underlying binding can get easily exchanged as well as adjusted if required without having to adjust all the user code
+
+
+
+ - This API layer should have certain pieces of information available to be able to, if required, forward such data to the SOVD Server for further processing there.
+ - as a result, user code must provide certain pieces of information as depicted by this design upon registration of SOVD Operations and/or Data Resources
+
+
+
+ - user code shall have minimal hassle w.r.t. to creating as well as having to populate native SOVD reply payloads
+ - ideally, the API layer shall create native SOVD data structures and populate these from the user code's data structures, e.g. to JSON
+
+
+
+ - user code which is still using legacy UDS APIs shall seamlessly continue to work as before
+ - such user code can then get migrated step-wise to new SOVD APIs which eases system migration to the new OpenSOVD stack
+
+
+
+ - newly written applications shall not use the legacy UDS APIs but the native SOVD ones instead
+
+## Diagrams
+
+
+A [PlantUML version](./cpp_abstraction_layer_api_for_user_applications.puml) is also available.
+
+## Coding Examples
+
+### UDS: ReadDataByIdentifier
+
+```cpp
+#include "mw/diag/uds/uds.hpp" // illustrative include
+
+#include
+
+class VinReader final : public mw::diag::uds::ReadDataByIdentifier
+{
+ public:
+ explicit VinReader(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::Result Read() override
+ {
+ ByteVector bytes{&memory_resource_};
+ bytes.insert(bytes.end(), {0x56, 0x49, 0x4E}); // "VIN" bytes, example only
+ return {std::move(bytes)};
+ }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterVinReader(std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::uds::DiagnosticServicesCollectionBuilder{memory_resource}
+ .With("0xF190") // note that `With()` will implicitly forward the builder's memory_resource to `VinReader`
+ .Build();
+}
+```
+
+### UDS: WriteDataByIdentifier
+
+```cpp
+#include "mw/diag/uds/uds.hpp" // illustrative include
+
+#include
+
+class ConfigWriter final : public mw::diag::uds::WriteDataByIdentifier
+{
+ public:
+ explicit ConfigWriter(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::Result Write(mw::diag::ByteSequence data) override
+ {
+ // parse and persist `data` here
+
+ return {};
+ }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterConfigWriter(std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::uds::DiagnosticServicesCollectionBuilder{memory_resource}
+ .With("0xF191") // note that `With()` will implicitly forward the builder's memory_resource to `ConfigWriter`
+ .Build();
+}
+```
+
+### UDS: RoutineControl
+
+```cpp
+#include "mw/diag/uds/uds.hpp" // illustrative include
+
+#include
+
+class MyRoutine final : public mw::diag::uds::RoutineControl
+{
+ public:
+ explicit MyRoutine(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::Result Start(ByteSequence request) override
+ {
+ // implement your logic for start routine here
+
+ ByteVector bytes{&memory_resource_};
+ bytes.push_back(0x00);
+ return {std::move(bytes)};
+ }
+
+ mw::diag::Result Stop(ByteSequence request) override
+ {
+ // implement your logic for stop routine here
+
+ ByteVector bytes{&memory_resource_};
+ bytes.push_back(0x00);
+ return {std::move(bytes)};
+ }
+
+ mw::diag::Result RequestResults(ByteSequence request) override
+ {
+ // implement your logic for request routine results here
+
+ ByteVector bytes{memory_resource_};
+ bytes.insert(bytes.end(), {0x12, 0x34});
+ return {std::move(bytes)};
+ }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterMyRoutine(std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::uds::DiagnosticServicesCollectionBuilder{memory_resource}
+ .With("0xFF00") // note that `With()` will implicitly forward the builder's memory_resource to `MyRoutine`
+ .Build();
+}
+```
+
+### SOVD: ReadOnlyDataResource
+
+```cpp
+#include "mw/diag/sovd/sovd.hpp" // illustrative include
+
+#include
+
+class VehicleInfoResource final : public mw::diag::sovd::ReadOnlyDataResource
+{
+ public:
+ explicit VehicleInfoResource(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::sovd::Result Get() override
+ {
+ mw::diag::sovd::JsonDataReply reply;
+ // reply.set({{"vin", "FOO BAR"}}); // illustrative JSON
+ return {std::move(reply)};
+ }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterVehicleInfoResourceFor(mw::diag::sovd::DiagnosticEntity& entity,
+ mw::diag::sovd::JsonSchemaView json_schema,
+ std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::sovd::DiagnosticServicesCollectionBuilder{entity, memory_resource}
+ .With("common/VehicleInfoResource",
+ schema,
+ mw::diag::sovd::DataCategoryIdentifiers::kSysInfo,
+ std::nullopt) // note that `With()` will implicitly forward the builder's memory_resource to `VehicleInfoResource`
+ .Build();
+}
+```
+
+### SOVD: WritableDataResource
+
+```cpp
+#include "mw/diag/sovd/sovd.hpp" // illustrative include
+
+#include
+
+class ConfigResource final : public mw::diag::sovd::WritableDataResource
+{
+ public:
+ explicit ConfigResource(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::sovd::Result Put(mw::diag::sovd::DiagnosticRequest request) override
+ {
+ // parse `request.data` and persist it here as required by your needs
+
+ return {};
+ }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterConfigResourceFor(mw::diag::sovd::DiagnosticEntity& entity, std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::sovd::DiagnosticServicesCollectionBuilder{entity, memory_resource}
+ .With("MyApplication/MyComponent/Configure",
+ mw::diag::sovd::DataCategoryIdentifiers::kParameter,
+ std::nullopt) // note that `With()` will implicitly forward the builder's memory_resource to `ConfigResource`
+ .Build();
+}
+```
+
+### SOVD: Operations
+
+```cpp
+#include "mw/diag/sovd/sovd.hpp" // illustrative include
+
+#include
+
+// synchronous operation
+class SelfTestOperation final : public mw::diag::sovd::Operation
+{
+ public:
+ explicit SelfTestOperation(std::pmr::memory_resource& memory_resource) : memory_resource_{memory_resource} {}
+
+ mw::diag::sovd::Result Info(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Status(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+
+ mw::diag::sovd::Result Execute(mw::diag::sovd::DiagnosticRequest) override
+ {
+ // perform operation in place here (=> synchronously)
+
+ return {};
+ }
+
+ mw::diag::sovd::Result Resume(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Reset(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Stop(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+// asynchronous operation
+class LongRunningOperation final : public mw::diag::sovd::Operation
+{
+ public:
+ explicit LongRunningOperation(std::pmr::memory_resource& memory_resource) : memory_resource_(memory_resource) {}
+
+ mw::diag::sovd::Result Info(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Status(mw::diag::sovd::DiagnosticRequest) override
+ {
+ // return current progress/status
+ return {};
+ }
+
+ mw::diag::sovd::Result Execute(mw::diag::sovd::DiagnosticRequest) override
+ {
+ // trigger async work here and return initial response
+ return {};
+ }
+
+ mw::diag::sovd::Result Resume(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Reset(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+ mw::diag::sovd::Result Stop(mw::diag::sovd::DiagnosticRequest) override { return {}; }
+
+ private:
+ std::pmr::memory_resource& memory_resource_;
+};
+
+mw::diag::Result>
+RegisterOperationsFor(mw::diag::sovd::DiagnosticEntity& entity, std::pmr::memory_resource& memory_resource)
+{
+ return mw::diag::sovd::DiagnosticServicesCollectionBuilder{entity, memory_resource}
+ .With("MyApplication/MyComponent/PerformSelfTest",
+ mw::diag::sovd::OperationInvocationPolicy::kPerformsSynchronousInvocation,
+ std::nullopt) // note that `With()` will implicitly forward the builder's memory_resource to `SelfTestOperation`
+ .With("MyApplication/MyComponent/PerformLongRunningTask",
+ mw::diag::sovd::OperationInvocationPolicy::kRequiresIndividualAsyncInvocations,
+ std::nullopt) // note that `With()` will implicitly forward the builder's memory_resource to `LongRunningOperation`
+ .Build();
+}
+```
diff --git a/docs/design/cpp_abstraction_layer_api_for_user_applications.puml b/docs/design/cpp_abstraction_layer_api_for_user_applications.puml
new file mode 100755
index 0000000..670b6a3
--- /dev/null
+++ b/docs/design/cpp_abstraction_layer_api_for_user_applications.puml
@@ -0,0 +1,426 @@
+@startuml CppAbstractionLayerAPIForDiagnosticServices
+
+!theme plain
+skinparam classAttributeIconSize 0
+skinparam classFontSize 11
+skinparam packageStyle rectangle
+
+package "Design Goals" as DesignGoals {}
+package "see cpp_abstraction_layer_api_for_user_applications.md" as DesignGoals.Reference {}
+
+package "mw::diag" {
+ enum ErrorCode {
+ kUnknown
+ kInternalError
+ }
+
+ entity "Result" as DiagResult {
+ alias for `score::Result`
+ }
+
+ entity ByteSequence {
+ <>
+ ByteSequence = std::span
+ }
+
+ entity ByteVector {
+ <>
+ ByteVector = std::pmr::vector
+ }
+
+ abstract class DiagnosticServicesCollection {
+ no public methods are defined since lifetime control of contained services is the only goal of this class
+ }
+}
+
+package "mw::diag::sovd" {
+ class "Error" as SOVDError {
+ sovd_error : std::pmr::string
+ vendor_error : std::pmr::string
+ vendor_message : std::pmr::string
+ }
+
+ class "Result" as SOVDResult {
+ alias for `score::details::expected`
+ }
+
+ class TranslationIdentifier {}
+ class DataCategoryIdentifier {}
+ class DataGroupIdentifier {}
+ class DataGroupShortDesc {}
+ class JsonSchemaView {}
+
+ enum DataCategoryIdentifiers {
+ kIdentification = 'identData'
+ kMeasurement = 'currentData'
+ kParameter = 'storedData'
+ kSysInfo = 'sysInfo'
+ }
+
+ enum OperationInvocationPolicy {
+ kPerformsSynchronousInvocation
+ kRequiresIndividualAsyncInvocations
+ kSupportsConcurrentAsyncInvocations
+ }
+
+ enum ProximityProof {
+ kRequired
+ kNotRequired
+ }
+
+ enum "DiagnosticEntity::Kind" as DiagnosticEntityKind {
+ kApplication
+ }
+
+ class "DiagnosticEntity::Mode" as DiagnosticEntityMode {
+ +id : std::pmr::string
+ +name : std::pmr::string
+ +translation_id : std::optional
+ +values : std::pmr::vector
+ }
+
+ class DiagnosticEntity {
+ using Identifier = std::pmr::string
+ ..
+ #TO BE CLARIFIED: are these two required here or will locking be handled completely by SOVD Server instead?
+ #{abstract} Lock() : mw::diag::sovd::Result
+ #{abstract} Unlock() : mw::diag::sovd::Result
+ ..
+ {abstract} GetKind() : DiagnosticEntity::Kind
+ ..
+ {abstract} GetSupportedModes() : mw::diag::sovd::Result>
+ {abstract} ApplyMode(mode_id : std::pmr::string, mode_value : std::pmr::string, expiration_timeout : std::optional) : mw::diag::sovd::Result
+ }
+
+ class "DiagnosticServicesCollection" as SOVDDiagnosticServicesCollection {
+ +explicit DiagnosticServicesCollection(DiagnosticEntity&, std::pmr::memory_resource&)
+ ~DiagnosticServicesCollection()
+ }
+ note right: upon destruction, will release all functionality as well as\nregistered services of the referenced DiagnosticEntity from\nthe underlying binding implementation
+
+ class "DiagnosticServicesCollectionBuilder" as SOVDDiagnosticServicesCollectionBuilder {
+ +using Identifier = std::string_view
+
+ +explicit DiagnosticServicesCollectionBuilder(DiagnosticEntity&, std::pmr::memory_resource&)
+
+ +With(Identifier, JsonSchemaView, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, JsonSchemaView, DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(DataCategoryIdentifier, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(DataGroupIdentifier, DataGroupShortDesc, std::optional, DataCategoryIdentifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, OperationInvocationPolicy, std::optional, Args&&...) : DiagnosticServicesCollectionBuilder&
+
+ .. final step ..
+ +Build() : mw::diag::Result>
+ }
+}
+
+package "mw::diag::sovd" {
+ class DiagnosticRequest {
+ +headers : std::pmr::unordered_map
+ +proximity_response: std::optional
+ +data : JSON
+ }
+
+ class DiagnosticReply {
+ #TODO: add public Getters/Setters!
+ --
+ -headers_ : std::pmr::unordered_map
+ }
+
+ class ProximityChallenge {
+ +challenge : std::pmr::string
+ +valid_until : time_point
+ }
+
+ class JsonDataReply {
+ #TODO: add public Getters/Setters!
+ --
+ -data_ : JSON -> json data created from content of deriving classes
+ }
+
+ interface ReadOnlyDataResource {
+ API definition for read-only SOVD data resources
+
+ {abstract} Get() : mw::diag::sovd::Result
+ }
+
+ interface WritableDataResource {
+ API definition for writable SOVD data resources
+
+ {abstract} Put(DiagnosticRequest) : mw::diag::sovd::Result
+ }
+
+ interface DataResource {
+ API definition for SOVD data resources
+ }
+
+ enum OperationExecutionStatus {
+ kFailed
+ kRunning
+ kStopped
+ kCompleted
+ }
+
+ class OperationInfoReply {
+ #TODO: add public Getters/Setters!
+ --
+ -supported_modes_ : std::pmr::vector
+ }
+
+ class OperationStatusReply {
+ #TODO: add public Getters/Setters!
+ --
+ -capability_ : std::pmr::string
+ -parameters_ : JSON
+ }
+
+ class ExecuteOperationReply {
+ #TODO: add public Getters/Setters!
+ }
+
+ interface Operation {
+ API definition for SOVD operations
+
+ .. standard SOVD capabilities ..
+ {abstract} Info(DiagnosticRequest) : mw::diag::sovd::Result
+ {abstract} Status(DiagnosticRequest) : mw::diag::sovd::Result
+ {abstract} Execute(DiagnosticRequest) : mw::diag::sovd::Result
+ {abstract} Resume(DiagnosticRequest) : mw::diag::sovd::Result
+ {abstract} Reset(DiagnosticRequest) : mw::diag::sovd::Result
+ {abstract} Stop(DiagnosticRequest) : mw::diag::sovd::Result
+
+ .. OEM-specific capabilities ..
+ .. only to be overridden by deriving classes if required ..
+ {abstract} Handle(DiagnosticRequest) : mw::diag::sovd::Result
+ }
+}
+
+package "mw::diag::uds" {
+ interface ReadDataByIdentifier {
+ API definition for UDS Service 'Read Data by Identifier'
+
+ {abstract} Read() : score::Result
+ }
+
+ interface WriteDataByIdentifier {
+ API definition for UDS Service 'Write Data by Identifier'
+
+ {abstract} Write(ByteSequence) : mw::diag::Result
+ }
+
+ abstract class DataIdentifier {
+ <>
+ }
+
+ interface RoutineControl {
+ API definition for UDS RoutineControl
+
+ {abstract} Start(ByteSequence) : Result
+ {abstract} Stop(ByteSequence) : Result
+ {abstract} RequestResults(ByteSequence) : Result
+ }
+
+ interface UDSService {
+ API definition for a generic UDS Service
+
+ {abstract} HandleMessage(ByteSequence) : score::Result
+ }
+
+ class "SerializedReadDataByIdentifier" as SerializedReadDataByIdentifier {
+ {abstract} Read() : Result {override}
+ }
+
+ class "SerializedWriteDataByIdentifier" as SerializedWriteDataByIdentifier {
+ {abstract} Write(ByteSequence) : mw::diag::Result {override}
+ }
+
+ class "SerializedDataByIdentifier" as SerializedDataByIdentifier {
+ {abstract} Read() : Result {override}
+ {abstract} Write(ByteSequence) : mw::diag::Result {override}
+ }
+
+ class "SerializedRoutineControl" as SerializedRoutineControl {
+ <>
+ }
+
+ enum UDSResponseCode {
+ kGeneralReject = 0x10
+ kServiceNotSupported = 0x11
+ kSubFunctionNotSupported = 0x12
+ kIncorrectMessageLengthOrInvalidFormat = 0x13
+ kResponseTooLong = 0x14
+ kBusyRepeatRequest = 0x21
+ kConditionsNotCorrect = 0x22
+ kNoResponseFromSubnetComponent = 0x23
+ kRequestSequenceError = 0x24
+ kNoResponseFromSubNetComponent = 0x25
+ kFailurePreventsExecutionOfRequestedAction = 0x26
+ kRequestOutOfRange = 0x31
+ kSecurityAccessDenied = 0x33
+ kAuthenticationRequired = 0x34
+ kInvalidKey = 0x35
+ kExceededNumberOfAttempts = 0x36
+ kRequiredTimeDelayNotExpired = 0x37
+ kSecureDataTransmissionRequired = 0x38
+ kSecureDataTransmissionNotAllowed = 0x39
+ kSecureDataVerificationFailed = 0x3A
+ kCertificateVerificationFailed_InvalidTimePeriod = 0x50
+ kCertificateVerificationFailed_InvalidSignature = 0x51
+ kCertificateVerificationFailed_InvalidChainOfTrust = 0x52
+ kCertificateVerificationFailed_InvalidType = 0x53
+ kCertificateVerificationFailed_InvalidFormat = 0x54
+ kCertificateVerificationFailed_InvalidContent = 0x55
+ kCertificateVerificationFailed_InvalidScope = 0x56
+ kCertificateVerificationFailed_InvalidCertificate = 0x57
+ kOwnershipVerificationFailed = 0x58
+ kChallengeCalculationFailed = 0x59
+ kSettingAccessRightsFailed = 0x5A
+ kSessionKeyCreationOrDerivationFailed = 0x5B
+ kConfigurationDataUsageFailed = 0x5C
+ kDeAuthenticationFailed = 0x5D
+ kUploadDownloadNotAccepted = 0x70
+ kTransferDataSuspended = 0x71
+ kGeneralProgrammingFailure = 0x72
+ kWrongBlockSequenceCounter = 0x73
+ kRequestCorrectlyReceived_ResponsePending = 0x78
+ kSubFunctionNotSupportedInActiveSession = 0x7E
+ kServiceNotSupportedInActiveSession = 0x7F
+ kRpmTooHigh = 0x81
+ kRpmTooLow = 0x82
+ kEngineIsRunning = 0x83
+ kEngineIsNotRunning = 0x84
+ kEngineRunTimeTooLow = 0x85
+ kTemperatureTooHigh = 0x86
+ kTemperatureTooLow = 0x87
+ kVehicleSpeedTooHigh = 0x88
+ kVehicleSpeedTooLow = 0x89
+ kThrottleOrPedalTooHigh = 0x8A
+ kThrottleOrPedalTooLow = 0x8B
+ kTransmissionRangeNotInNeutral = 0x8C
+ kTransmissionRangeNotInGear = 0x8D
+ kBrakeSwitchOrSwitchesNotClosed = 0x8F
+ kShifterLeverNotInPark = 0x90
+ kTorqueConvertClutchLocked = 0x91
+ kVoltageTooHigh = 0x92
+ kVoltageTooLow = 0x93
+ kResourceTemporarilyNotAvailable = 0x94
+ }
+
+ class "DiagnosticServicesCollection" as UDSDiagnosticServicesCollection {
+ +explicit DiagnosticServicesCollection(std::pmr::memory_resource&)
+ ~DiagnosticServicesCollection()
+ }
+
+ class "DiagnosticServicesCollectionBuilder" as UDSDiagnosticServicesCollectionBuilder {
+ +using Identifier = std::string_view
+
+ +explicit DiagnosticServicesCollectionBuilder(std::pmr::memory_resource&)
+
+ +With(Identifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+ +With(Identifier, Args&&...) : DiagnosticServicesCollectionBuilder&
+
+ .. final step ..
+ +Build() : mw::diag::Result>
+ }
+
+ package "details" {
+ class SerializationHelper {
+ <>
+ +SerializeResponse(ResponsePayload) : mw::diag::Result
+ +SerializeRequest(ByteVector&, Callable&) : mw::diag::Result
+ }
+ }
+}
+
+' Relationships
+UDSDiagnosticServicesCollectionBuilder --> UDSDiagnosticServicesCollection : creates
+UDSDiagnosticServicesCollectionBuilder ..> DataIdentifier : accepts attempts to create objects inherting from
+UDSDiagnosticServicesCollectionBuilder ..> ReadDataByIdentifier : accepts attempts to create objects inherting from
+UDSDiagnosticServicesCollectionBuilder ..> WriteDataByIdentifier : accepts attempts to create objects inherting from
+UDSDiagnosticServicesCollectionBuilder ..> RoutineControl : accepts attempts to create objects inherting from
+UDSDiagnosticServicesCollectionBuilder ..> UDSService : accepts attempts to create objects inherting from
+
+UDSDiagnosticServicesCollection --|> DiagnosticServicesCollection : implements
+
+DataIdentifier --|> ReadDataByIdentifier : inherits
+DataIdentifier --|> WriteDataByIdentifier : inherits
+
+SerializedReadDataByIdentifier --|> ReadDataByIdentifier : inherits
+SerializedWriteDataByIdentifier --|> WriteDataByIdentifier : inherits
+SerializedDataByIdentifier --|> DataIdentifier : inherits
+SerializedRoutineControl --|> RoutineControl : inherits
+
+WriteDataByIdentifier ..> ByteSequence : consumes
+RoutineControl ..> ByteSequence : consumes
+UDSService ..> ByteSequence : consumes
+
+ReadDataByIdentifier ..> ByteVector : produces
+RoutineControl ..> ByteVector : produces
+UDSService ..> ByteVector : produces
+
+SerializationHelper ..> UDSResponseCode : uses
+SerializedReadDataByIdentifier ..> SerializationHelper : uses
+SerializedWriteDataByIdentifier ..> SerializationHelper : uses
+
+SOVDDiagnosticServicesCollectionBuilder ..> DiagnosticEntity : gets created using a particular
+SOVDDiagnosticServicesCollectionBuilder ..> ReadOnlyDataResource : accepts attempts to create objects inherting from
+SOVDDiagnosticServicesCollectionBuilder ..> WritableDataResource : accepts attempts to create objects inherting from
+SOVDDiagnosticServicesCollectionBuilder ..> DataResource : accepts attempts to create objects inherting from
+SOVDDiagnosticServicesCollectionBuilder ..> Operation : accepts attempts to create objects inherting from
+
+OperationInvocationPolicy ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+DataCategoryIdentifiers ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+TranslationIdentifier ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+DataCategoryIdentifier ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+DataGroupIdentifier ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+DataGroupShortDesc ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+JsonSchemaView ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+ProximityProof ..> SOVDDiagnosticServicesCollectionBuilder : users provide to
+
+SOVDDiagnosticServicesCollection --|> DiagnosticServicesCollection : implements
+SOVDDiagnosticServicesCollection o--> DiagnosticEntity : requires
+DiagnosticEntity --> DiagnosticEntityMode : supports certain
+DiagnosticEntity --> DiagnosticEntityKind : is of
+
+DataResource --|> ReadOnlyDataResource : inherits
+DataResource --|> WritableDataResource : inherits
+
+ReadOnlyDataResource ..> DiagnosticRequest : consumes
+ReadOnlyDataResource ..> SOVDResult : produces
+WritableDataResource ..> DiagnosticRequest : consumes
+WritableDataResource ..> JsonDataReply : produces
+WritableDataResource ..> SOVDResult : produces
+
+Operation ..> DiagnosticRequest : consumes
+Operation ..> ExecuteOperationReply : produces
+Operation ..> OperationStatusReply : produces
+Operation ..> OperationInfoReply : produces
+Operation ..> JsonDataReply : produces
+Operation ..> SOVDResult : produces
+
+JsonDataReply --|> DiagnosticReply : inherits
+
+OperationInfoReply --|> JsonDataReply : inherits
+OperationStatusReply --|> JsonDataReply : inherits
+ExecuteOperationReply --|> JsonDataReply : inherits
+
+OperationInfoReply *- ProximityChallenge : contains
+OperationStatusReply *- OperationExecutionStatus : contains
+ExecuteOperationReply *- OperationExecutionStatus : contains
+
+SOVDResult ..> SOVDError : uses
+
+DiagResult ..> ErrorCode : uses
+
+note right of UDSDiagnosticServicesCollectionBuilder : Builder pattern for creating\ndiagnostic services collections.\nSupports fluent API via `With<>()` methods\nfor different service types.
+note right of SOVDDiagnosticServicesCollectionBuilder : Builder pattern for creating\ndiagnostic services collections.\nSupports fluent API via `With<>()` methods\nfor different service types.
+
+note bottom of DataIdentifier : Multiple inheritance interface\ncombining read and write capabilities
+
+note bottom of SerializedDataByIdentifier : CRTP pattern for automatic\nserialization/deserialization
+
+@enduml
diff --git a/docs/design/cpp_abstraction_layer_api_for_user_applications.svg b/docs/design/cpp_abstraction_layer_api_for_user_applications.svg
new file mode 100644
index 0000000..d6474c3
--- /dev/null
+++ b/docs/design/cpp_abstraction_layer_api_for_user_applications.svg
@@ -0,0 +1 @@
+
\ No newline at end of file