From d98ff983b0d3e3a2d550ade6cbe98a4d058f2f16 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Mon, 5 May 2025 14:19:06 +0200 Subject: [PATCH 001/102] diagnostics: create initial draft feature request inital draft includes proposed architecture of diagnostic system --- .../score-diagnostics-draft.drawio.svg | 1305 +++++++++++++++++ docs/features/diagnostics/index.rst | 315 ++++ docs/requirements/stakeholder/index.rst | 10 + 3 files changed, 1630 insertions(+) create mode 100644 docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg create mode 100644 docs/features/diagnostics/index.rst diff --git a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg new file mode 100644 index 0000000000..af8142ee5d --- /dev/null +++ b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg @@ -0,0 +1,1305 @@ + + + + + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ SOVD Server +
+
+
+
+ + SOVD Server + +
+
+
+ + + + + + + +
+
+
+ SOVD Client (offboard, onboard, cloud) +
+
+
+
+ + SOVD Client (offboar... + +
+
+
+ + + + + + + +
+
+
+ UDS2SOVD +
+ Proxy +
+
+
+
+
+ + UDS2SOVD... + +
+
+
+ + + + + + + +
+
+
+ Classic Diagnostic +
+ Adapter +
+
+
+
+
+ + Classic Diagnostic... + +
+
+
+ + + + + + + +
+
+
+ Crypto +
+
+
+
+ + Crypto + +
+
+
+ + + + + + + +
+
+
+ activity +
+
+
+
+ + activity + +
+
+
+ + + + + + + +
+
+
+ activity +
+
+
+
+ + activity + +
+
+
+ + + + + + + +
+
+
+ activity +
+
+
+
+ + activity + +
+
+
+ + + + + + + +
+
+
+ activity +
+
+
+
+ + activity + +
+
+
+ + + + + + + +
+
+
+ F lib +
+
+
+
+ + F lib + +
+
+
+ + + + + + + +
+
+
+ F lib +
+
+
+
+ + F lib + +
+
+
+ + + + + + + +
+
+
+ F lib +
+
+
+
+ + F lib + +
+
+
+ + + + + + + +
+
+
+ F lib +
+
+
+
+ + F lib + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ Diagnostic Fault Manager +
+
+
+
+ + Diagnostic Fault Man... + +
+
+
+ + + + + + + +
+
+
+ Service App +
+
+
+
+ + Service App + +
+
+
+ + + + + + + +
+
+
+ Configuration Manager +
+
+
+
+ + Configuration Manager + +
+
+
+ + + + + + + + +
+
+
+ Diagnostic DB +
+
+
+
+ + Diagnostic... + +
+
+
+ + + + + + + +
+
+
+ Rest of Vehicle UDS +
+
+
+
+ + Rest of Vehicle UDS + +
+
+
+ + + + + + + +
+
+
+ Rest of Vehicle SOVD +
+
+
+
+ + Rest of Vehicle SOVD + +
+
+
+ + + + + + + +
+
+
+ SOVD Gateway +
+
+
+
+ + SOVD Gateway + +
+
+
+ + + + + + + +
+
+
+ UDS Tester +
+
+
+
+ + UDS Tester + +
+
+
+ + + + + + + +
+
+
+ Flash Service App +
+
+
+
+ + Flash Service App + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ Extends +
+
+
+
+ + Extends + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ UDS +
+
+
+
+ + UDS + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ UDS +
+
+
+
+ + UDS + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + +
+
+
+ odx +
+
+
+
+ + odx + +
+
+
+ + + + + + + +
+
+
+ Out of scope +
+
+
+
+ + Out of scope + +
+
+
+ + + + + + + +
+
+
+ In scope +
+
+
+
+ + In scope + +
+
+
+ + + + + + + +
+
+
+ + Legend + +
+
+
+
+ + Legend + +
+
+
+ + + + + + + + +
+
+
+ configures +
+
+
+
+ + configures + +
+
+
+ + + + + + + + +
+
+
+ file +
+
+
+
+ + file + +
+
+
+ + + + + + + + +
+
+
+ DB +
+
+
+
+ + DB + +
+
+
+ + + + + + + +
+
+
+ FEO activity +
+
+
+
+ + FEO activity + +
+
+
+ + + + + + + +
+
+
+ DRAFT: S-CORE Diagnostic Stack +
+
+
+
+ + DRAFT: S... + +
+
+
+ + + + + + + +
+
+
+ Authentication Manager +
+
+
+
+ + Authentication Manag... + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + +
+
+
+ odx +
+
+
+
+ + odx + +
+
+
+ + + + + + + + +
+
+
+ configures +
+
+
+
+ + configures + +
+
+
+ + + + + + + +
+
+
+ Persistency +
+
+
+
+ + Persistency + +
+
+
+ + + + + + + + +
+
+
+ Use +
+
+
+
+ + Use + +
+
+
+ + + + + + + + + +
+
+
+ HPC +
+
+
+
+ + HPC + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
\ No newline at end of file diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst new file mode 100644 index 0000000000..68f185097c --- /dev/null +++ b/docs/features/diagnostics/index.rst @@ -0,0 +1,315 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _diagnostics_feature: + +Diagnostics +############ + +.. note:: Diagnostics + +.. document:: Diagnostics + :id: doc__diagnostics + :status: draft + :safety: QM + :tags: feature_request + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_diagnostics`` + + +Abstract +======== + +We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. +SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, +eliminating the need for manually modeling diagnostic interfaces as required in UDS. +This signifi-cantly reduces integration overhead and simplifies the onboarding of new ECUs. +Additionally, SOVD ena-bles scalable, secure, and cloud-ready diagnostics with real-time fault access and +advanced data han-dling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, +improve system maintainability, and support future-proof diagnostic workflows. + +The intent of this feature request is to define a high-level architecture for the diagnostic system. +The com-ponents listed throughout this document require detailed feature requests in the future respectively. + + +Motivation +========== + +Currently there is no solution for vehicle diagnostics in S-CORE. +Diagnostic is a core capability of automotive platform stacks and is required for various use-cases +such as field troubleshooting, quality assurance, after sales, production, development and more. + + +Rationale +========= + +[Describe why particular design decisions were made.] + + + .. note:: + The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. + + +Specification +============= + + +Architecture +------------ + +The proposed concept consists of three main parts: + +1. A library to aggregate faults and integrate the diagnostic system into S-CORE +2. A SOVD based diagnostic system +3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs + +The diagram below shows the entire concept with the three subgroups connected. + +.. image:: _assets/score-diagnostics-draft.drawio.svg + :alt: Diagnostic stack component architecture + + +In scope components +------------------- + +The following components are considered in scope of this feature request. + +F lib (Fault Library) + +- Provides an interface for FEO activities to report faults. +- Relays faults via IPC to central Diagnostic Fault Manager. +- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration inter-face +- Reporting of faults additionally results in a log entry. +- The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. +- F lib is the base for activity specific, custom fault handling. + +Diagnostic Fault Manager + +- Aggregates and manages diagnostic fault data from F libs across the system. +- Provides centralized fault status to the SOVD Server. +- Interfaces with the Diagnostic DB (persistency) to store and retrieve data. +- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by F libs. + +Diagnostic DB + +- Stores static and runtime diagnostic data +- Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. +- The data format needs to be specified further but will likely include: +- Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. +- Fault ID (FID): ECU specific ID to uniquely identify every fault. +- Count: occurrence count of DTC/fault. +- Meta data: meta data related to fault occurrence. + +SOVD Server + +- Central entry point for all diagnostic requests via SOVD. +- Implements the SOVD API and dispatches requests to services, DB, and fault manager. +- Manages authentication, configuration, and data access via IPC. + +Service App + +- Is a base concept to extend the system with system-specific diagnostic ser-vices/routines (e.g., DTC clear, ECU reset, Flash Master). +- Interfaces with the SOVD Server via IPC. + +SOVD Gateway + +- Forwards SOVD requests to appropriate backend targets (e.g., adapters, proxies, cli-ents). +- Acts as a router between clients and distributed SOVD components. +- Supports multi-ECU SOVD communication. + +SOVD Client + +- Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. +- Can be used by developers, testers, ECUs or cloud services- should be deployment ag-nostic. +- Handles access control on the client side – e.g. by providing relevant certificates. + +Classic Diagnostic Adapter + +- Translates SOVD service calls to UDS commands. +- Enables backward compatibility with legacy ECUs that only support UDS. +- Configured via ODX files describing ECU-specific UDS expectations. + +UDS2SOVD Proxy + +- Exposes selected SOVD functionality via UDS for backward-compatible testers. +- Acts as a local translation layer between UDS clients and SOVD stack. +- Configured using a ODX to define what is exposed. + + +Out of scope components +----------------------- + +The following components are out of scope for this feature request but are included for context. +Each is briefly described to illustrate its role within the overall system architecture and +to highlight any resulting requirements or constraints imposed by the diagnostic system design. + +Configuration Manager + +- Provides configuration data to the SOVD Server (e.g., ECU layout, variant, parameters). +- Enables parametrization of applications. + +Authentication Manager + +- Manages authentication and authorization for incoming SOVD requests. +- Ensures only valid users or clients can access services. + +Crypto + +- Provides cryptographic services – e.g. securely store and retrieve diagnostic certifi-cates. +- Used by Authentication Manager. + +Persistency + +- Provides persistent data storage. + +Flash Service App + +- Specialized extension of the Service App to handle ECU flashing. +- Provides routines for software update/bootloader access via diagnostics. + +Rest of Vehicle UDS + +- Represents legacy ECUs in the vehicle that only speak UDS. +- Interact via the Classic Diagnostic Adapter (SOVD2UDS). + +Rest of Vehicle SOVD + +- Other ECUs in the vehicle that already support SOVD natively. +- Can communicate directly with the SOVD Gateway. + +UDS Tester + +- Traditional diagnostics tester that uses UDS protocol. +- Communicates with the UDS2SOVD Proxy for limited diagnostics access. + + +Requirements +------------ + +The following section includes unordered and incomplete feature requirements. + +.. feat_req:: SOVD Standard + :id: feat_req__diagnostics__sovd_std + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The SOVD implementation shall conform to the SOVD standard as defined in ISO/DIS 17978 (or the latest available draft or final publication). + +.. feat_req:: OEM Diagnostic Plug In + :id: feat_req__diagnostics__oem_plugin + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The diagnostic system shall provide a plug-in mechanism to include OEM-specific features. + +.. feat_req:: Diagnostic system internal communication + :id: feat_req__diagnostics__internal_com + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + All internal communication between diagnostic components that do not use UDS or SOVD protocols shall be implemented using the S-CORE::COM middleware. + + +Backwards Compatibility +======================= + +UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. +ODX as a standardized exchange format further ensure compatibility with proprietary diagnos-tic data models. + + +Security Impact +=============== + +[How could a malicious user take advantage of this new/modified feature?] + + .. note:: + If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which security requirements are affected or has to be changed? +Could the new/modified feature enable new threat scenarios? +Could the new/modified feature enable new attack paths? +Could the new/modified feature impact functional safety? +If applicable, which additional security measures must be implemented to mitigate the risk? + + .. note:: + Use Trust Boundary, Defense in Depth Analysis and/or Security Software Critically Analysis, + Vulnerability Analysis. + [Methods will be defined later in Process area Security Analysis] + + +Safety Impact +============= + +At this point in time no safety impact is foreseen. The expected ASIL level is QM. +Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. + + +License Impact +============== + +There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. +While SOVD is currently in the ISO standardization process (ISO/DIS 17978), the relevant parts—especially Part 3, +which defines the API—are already publicly available for purchase as Draft Interna-tional Standards (DIS). +These drafts are considered stable and are typically subject only to minor edito-rial changes before final publication. +As such, referencing the current DIS versions is sufficient for im-plementation purposes, and does not pose any legal or license-related risk. +Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. + +The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. + + +How to Teach This +================= + +[How to teach users, new and experienced, how to apply the CR to their work.] + + .. note:: + For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. + + +Rejected Ideas +============== + +An UDS first based diagnostic system was considered but rejected. +The current market trend clearly indicates the move towards SOVD. +Additionally, there a multiple well established proprietary UDS stacks and tools available. +Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CORE to provide value and increase adoption. + + +Open Issues +=========== + +- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed-stacks and/or a transition-al phase +- Investigate synergies between Configuration Manager and central diagnostic configuration file in Diagnostic Fault Manager +- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 + + +Footnotes +========= + +[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 341111d729..7a69c721cf 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -210,6 +210,16 @@ Functional requirements * debugging * feature activation +.. stkh_req:: Readout DTCs via SOVD + :id: stkh_req__diagnostics__dtc_read_sovd + :reqtype: Functional + :security: YES + :safety: QM + :rationale: tbd + :status: valid + + The system shall provide users the ability to retrieve current Diagnostic Trouble Codes (DTCs) from the ECU via the SOVD protocol. + Dependability ------------- From 2bfdf70e5847f1c2b77bef48408db7de7a23f16c Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Thu, 8 May 2025 09:46:33 +0200 Subject: [PATCH 002/102] diagnostics: draft feature request review ready inital draft of S-CORE diagnostic system ready for first review --- docs/features/diagnostics/index.rst | 50 ++++++++++++----------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 68f185097c..becaacb5a5 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -17,8 +17,6 @@ Diagnostics ############ -.. note:: Diagnostics - .. document:: Diagnostics :id: doc__diagnostics :status: draft @@ -60,11 +58,9 @@ such as field troubleshooting, quality assurance, after sales, production, devel Rationale ========= -[Describe why particular design decisions were made.] - - - .. note:: - The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. +SOVD was chosen as the foundation for the diagnostic architecture because it offers a modern, +service-oriented approach that aligns with the industry's shift toward Ethernet-based communication and scalable software-defined vehicle platforms. +It provides a standardized and extensible interface that enables better interoperability across ECUs, testers, and external tools. Specification @@ -246,35 +242,33 @@ ODX as a standardized exchange format further ensure compatibility with propriet Security Impact =============== -[How could a malicious user take advantage of this new/modified feature?] - - .. note:: - If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which security requirements are affected or has to be changed? -Could the new/modified feature enable new threat scenarios? -Could the new/modified feature enable new attack paths? -Could the new/modified feature impact functional safety? -If applicable, which additional security measures must be implemented to mitigate the risk? - - .. note:: - Use Trust Boundary, Defense in Depth Analysis and/or Security Software Critically Analysis, - Vulnerability Analysis. - [Methods will be defined later in Process area Security Analysis] +The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. +Diagnostics inherently allow access to system information, state manipulation, coding, and software updates—all of which pose risks if accessed by unauthorized actors. +SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, +but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. +If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. +This may enable new threat scenarios and attack paths, particularly over external or less trusted networks. +To mitigate these risks, the diagnostic stack shall enforce secure communication via HTTPS, +authenticate endpoints using certificates (see architecture diagram), and implement strict access control mechanisms. +While diagnostics do not directly impact functional safety, a successful attack could indirectly influence safety-relevant functions +- for example by setting the system into a different state. +Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. Safety Impact ============= -At this point in time no safety impact is foreseen. The expected ASIL level is QM. +At this point in time no direct safety impact is foreseen. The expected ASIL level is QM. Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. +As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions +- for example by setting the system into a different state. License Impact ============== There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. -While SOVD is currently in the ISO standardization process (ISO/DIS 17978), the relevant parts—especially Part 3, +While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts—especially Part 3, which defines the API—are already publicly available for purchase as Draft Interna-tional Standards (DIS). These drafts are considered stable and are typically subject only to minor edito-rial changes before final publication. As such, referencing the current DIS versions is sufficient for im-plementation purposes, and does not pose any legal or license-related risk. @@ -286,10 +280,7 @@ The license impact regarding publication of XML schemata to handle/convert ODX f How to Teach This ================= -[How to teach users, new and experienced, how to apply the CR to their work.] - - .. note:: - For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. +A good starting point to get an overview of SOVD is the overview pages provided by ISO [#s1]_ and ASAM [#s2]_. Rejected Ideas @@ -312,4 +303,5 @@ Open Issues Footnotes ========= -[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] +.. [#s1] "SOVD Standard ISO/DIS 17978", ISO, https://www.iso.org/standard/85133.html. +.. [#s2] "ASAM SOVD Overview", ASAM, https://www.asam.net/standards/detail/sovd. From 1100114663876205c7fbb7a2d6e96e7aae6a96f0 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Thu, 8 May 2025 11:03:36 +0200 Subject: [PATCH 003/102] diagnostics: draft feature request review ready fixed typos --- docs/features/diagnostics/index.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index becaacb5a5..d424efdbe0 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -38,13 +38,13 @@ Abstract We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, eliminating the need for manually modeling diagnostic interfaces as required in UDS. -This signifi-cantly reduces integration overhead and simplifies the onboarding of new ECUs. -Additionally, SOVD ena-bles scalable, secure, and cloud-ready diagnostics with real-time fault access and -advanced data han-dling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, +This significantly reduces integration overhead and simplifies the onboarding of new ECUs. +Additionally, SOVD enables scalable, secure, and cloud-ready diagnostics with real-time fault access and +advanced data handling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, improve system maintainability, and support future-proof diagnostic workflows. The intent of this feature request is to define a high-level architecture for the diagnostic system. -The com-ponents listed throughout this document require detailed feature requests in the future respectively. +The components listed throughout this document require detailed feature requests in the future respectively. Motivation @@ -91,7 +91,7 @@ F lib (Fault Library) - Provides an interface for FEO activities to report faults. - Relays faults via IPC to central Diagnostic Fault Manager. -- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration inter-face +- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface - Reporting of faults additionally results in a log entry. - The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. - F lib is the base for activity specific, custom fault handling. @@ -121,19 +121,19 @@ SOVD Server Service App -- Is a base concept to extend the system with system-specific diagnostic ser-vices/routines (e.g., DTC clear, ECU reset, Flash Master). +- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g., DTC clear, ECU reset, Flash Master). - Interfaces with the SOVD Server via IPC. SOVD Gateway -- Forwards SOVD requests to appropriate backend targets (e.g., adapters, proxies, cli-ents). +- Forwards SOVD requests to appropriate backend targets (e.g., adapters, proxies, clients). - Acts as a router between clients and distributed SOVD components. - Supports multi-ECU SOVD communication. SOVD Client - Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. -- Can be used by developers, testers, ECUs or cloud services- should be deployment ag-nostic. +- Can be used by developers, testers, ECUs or cloud services- should be deployment agnostic. - Handles access control on the client side – e.g. by providing relevant certificates. Classic Diagnostic Adapter @@ -168,7 +168,7 @@ Authentication Manager Crypto -- Provides cryptographic services – e.g. securely store and retrieve diagnostic certifi-cates. +- Provides cryptographic services – e.g. securely store and retrieve diagnostic certificates. - Used by Authentication Manager. Persistency @@ -236,7 +236,7 @@ Backwards Compatibility ======================= UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. -ODX as a standardized exchange format further ensure compatibility with proprietary diagnos-tic data models. +ODX as a standardized exchange format further ensure compatibility with proprietary diagnostic data models. Security Impact @@ -269,9 +269,9 @@ License Impact There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts—especially Part 3, -which defines the API—are already publicly available for purchase as Draft Interna-tional Standards (DIS). -These drafts are considered stable and are typically subject only to minor edito-rial changes before final publication. -As such, referencing the current DIS versions is sufficient for im-plementation purposes, and does not pose any legal or license-related risk. +which defines the API—are already publicly available for purchase as Draft International Standards (DIS). +These drafts are considered stable and are typically subject only to minor editorial changes before final publication. +As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. @@ -295,7 +295,7 @@ Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CO Open Issues =========== -- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed-stacks and/or a transition-al phase +- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase - Investigate synergies between Configuration Manager and central diagnostic configuration file in Diagnostic Fault Manager - Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 From e7b4ba6dc9db3e6f3df74955a13638ac67f4eefb Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Tue, 13 May 2025 10:53:34 +0200 Subject: [PATCH 004/102] feedback from architecture community updated document to show framework agnostic design + naming --- .gitignore | 3 + .../score-diagnostics-draft.drawio.svg | 794 ++++++++---------- docs/features/diagnostics/index.rst | 12 +- 3 files changed, 365 insertions(+), 444 deletions(-) diff --git a/.gitignore b/.gitignore index 421cd8aaad..c95b6c59b7 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ styles/ .venv __pycache__/ /.coverage + +# Mac +.DS_Store diff --git a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg index af8142ee5d..37c605ec8a 100644 --- a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg +++ b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg @@ -1,37 +1,15 @@ - + - - + -
-
-
- IPC -
-
-
-
- - IPC - -
-
-
- - - - - - - -
+
SOVD Server @@ -39,20 +17,20 @@
- + SOVD Server - + -
+
SOVD Client (offboard, onboard, cloud) @@ -60,20 +38,20 @@
- + SOVD Client (offboar... - + -
+
UDS2SOVD @@ -84,20 +62,20 @@
- + UDS2SOVD... - + -
+
Classic Diagnostic @@ -108,210 +86,171 @@
- + Classic Diagnostic... - + -
+
- Crypto -
-
-
- - - Crypto - - - - - - - - - - - -
-
-
- activity -
-
-
-
- - activity - -
-
-
- - - - - - - -
-
-
- activity + Service App
- - activity + + Service App
- + -
+
- activity + Rest of Vehicle UDS
- - activity + + Rest of Vehicle UDS - + -
+
- activity + Rest of Vehicle SOVD
- - activity + + Rest of Vehicle SOVD - + -
+
- F lib + SOVD Gateway
- - F lib + + SOVD Gateway - + -
+
- F lib + UDS Tester
- - F lib + + UDS Tester - + -
+
- F lib + Flash Service App
- - F lib + + Flash Service App - + + + -
-
-
- F lib +
+
+
+ IPC
- - F lib + + IPC - - + + + -
+
IPC @@ -319,21 +258,22 @@
- + IPC - - + + + -
+
IPC @@ -341,390 +281,400 @@
- + IPC - - + + -
+
- IPC + Extends
- - IPC + + Extends - - + + + -
+
- IPC + SOVD
- - IPC + + SOVD - + + + -
-
-
- Diagnostic Fault Manager +
+
+
+ SOVD
- - Diagnostic Fault Man... + + SOVD - + + + -
-
-
- Service App +
+
+
+ UDS
- - Service App + + UDS - + + + -
-
-
- Configuration Manager +
+
+
+ SOVD
- - Configuration Manager + + SOVD - - + + + -
-
-
- Diagnostic DB +
+
+
+ SOVD
- - Diagnostic... + + SOVD - + + + -
-
-
- Rest of Vehicle UDS +
+
+
+ UDS
- - Rest of Vehicle UDS + + UDS - + + + -
-
-
- Rest of Vehicle SOVD +
+
+
+ SOVD
- - Rest of Vehicle SOVD + + SOVD - + + -
+
- SOVD Gateway + odx
- - SOVD Gateway + + odx - + -
+
- UDS Tester + Out of scope
- - UDS Tester + + Out of scope - + -
+
- Flash Service App + In scope
- - Flash Service App + + In scope - - + -
-
-
- IPC +
+
+
+ + Legend +
- - IPC + + Legend - - + + -
+
- IPC + configures
- - IPC + + configures - - + + -
-
-
- IPC +
+
+
+ file
- - IPC + + file - - + + -
-
-
- IPC +
+
+
+ DB
- - IPC + + DB - - - + -
-
-
- IPC +
+
+
+ App/FEO activity
- - IPC + + App/FEO act... - - - + -
-
-
- IPC +
+
+
+ DRAFT: S-CORE Diagnostic & Fault Management Stack
- - IPC + + DRAFT: S... - - - + + + -
+
IPC @@ -732,563 +682,527 @@
- + IPC - - - + + -
-
-
- IPC +
+
+
+ odx
- - IPC + + odx - - + + -
+
- Extends + configures
- - Extends + + configures - - - + + + -
-
-
- SOVD +
+
+
+ HPC
- - SOVD + + HPC - - - + -
-
-
- SOVD +
+
+
+ App
- - SOVD + + App - - - + -
-
-
- UDS +
+
+
+ Configuration Manager
- - UDS + + Configuration Manager - - - + -
-
-
- SOVD +
+
+
+ Authentication Manager
- - SOVD + + Authentication Manag... - - - + -
-
-
- SOVD +
+
+
+ Crypto
- - SOVD + + Crypto - - - + + + -
+
- UDS + IPC
- - UDS + + IPC - - - + + -
+
- SOVD + IPC
- - SOVD + + IPC - - + -
+
- odx + Diagnostic Fault Manager
- - odx + + Diagnostic Fault Man... - + + -
+
- Out of scope + Diagnostic DB
- - Out of scope + + Diagnostic... - + + -
-
-
- In scope +
+
+
+ IPC
- - In scope + + IPC - + + -
-
-
- - Legend - +
+
+
+ IPC
- - Legend + + IPC - - + + + -
+
- configures + IPC
- - configures + + IPC - - + -
+
- file + Persistency
- - file + + Persistency - - + + -
-
-
- DB +
+
+
+ Use
- - DB + + Use - + -
+
- FEO activity + F lib
- - FEO activity + + F lib - + -
+
-
- DRAFT: S-CORE Diagnostic Stack +
+ Activity
- - DRAFT: S... + + Activity - + -
+
- Authentication Manager -
-
-
- - - Authentication Manag... - - - - - - - - - - - - - -
-
-
- IPC + F lib
- - IPC + + F lib
- - + -
+
- odx + Logging
- - odx + + Logging - - + + -
+
- configures + Use
- - configures + + Use - + -
+
- Persistency + Activity
- - Persistency + + Activity - - + -
-
-
- Use +
+
+
+ F lib
- - Use + + F lib - - - + + -
-
-
- HPC +
+
+
+ IPC
- - HPC + + IPC @@ -1302,4 +1216,4 @@ - \ No newline at end of file + diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index d424efdbe0..de27828096 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -14,8 +14,8 @@ .. _diagnostics_feature: -Diagnostics -############ +Diagnostic and Fault Management +############################### .. document:: Diagnostics :id: doc__diagnostics @@ -72,7 +72,7 @@ Architecture The proposed concept consists of three main parts: -1. A library to aggregate faults and integrate the diagnostic system into S-CORE +1. A framework agnostic library to aggregate faults and integrate the diagnostic system into S-CORE 2. A SOVD based diagnostic system 3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs @@ -89,7 +89,7 @@ The following components are considered in scope of this feature request. F lib (Fault Library) -- Provides an interface for FEO activities to report faults. +- Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. - Relays faults via IPC to central Diagnostic Fault Manager. - Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface - Reporting of faults additionally results in a log entry. @@ -156,6 +156,10 @@ The following components are out of scope for this feature request but are inclu Each is briefly described to illustrate its role within the overall system architecture and to highlight any resulting requirements or constraints imposed by the diagnostic system design. +Logging + +- Enables the Fault Library to log fault events. + Configuration Manager - Provides configuration data to the SOVD Server (e.g., ECU layout, variant, parameters). From 16d4cdb9536739f75e47a6e3c8c7197d9c1ed7eb Mon Sep 17 00:00:00 2001 From: Andrey Babanin Date: Wed, 14 May 2025 13:52:08 +0200 Subject: [PATCH 005/102] docs: Add baselibs feature request --- .../baselibs/docs/requirements/index.rst | 56 +++++++ docs/features/baselibs/index.rst | 147 ++++++++++++++++++ docs/requirements/stakeholder/index.rst | 11 ++ 3 files changed, 214 insertions(+) create mode 100644 docs/features/baselibs/docs/requirements/index.rst create mode 100644 docs/features/baselibs/index.rst diff --git a/docs/features/baselibs/docs/requirements/index.rst b/docs/features/baselibs/docs/requirements/index.rst new file mode 100644 index 0000000000..e840f0be54 --- /dev/null +++ b/docs/features/baselibs/docs/requirements/index.rst @@ -0,0 +1,56 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Requirements +############ + +.. feat_req:: Core Software Utilities + :id: feat_req__baselibs__core_utilities + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__base_libraries + :status: valid + + The base libraries shall include core software utilities and common infrastructure components needed by multiple platform modules. + +.. feat_req:: Multi-Language APIs + :id: feat_req__baselibs__multi_language_apis + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__base_libraries, stkh_req__dev_experience__prog_languages + :status: valid + + The base libraries shall provide APIs for C++, Rust, or both, depending on the requirements of consuming platform components. + +.. feat_req:: Consistent APIs + :id: feat_req__baselibs__consistent_apis + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__base_libraries, stkh_req__dev_experience__prog_languages, stkh_req__overall_goals__reuse_of_app_soft + :status: valid + + The base libraries shall provide consistent APIs while respecting language-specific idioms. + +.. feat_req:: Maintainable Design + :id: feat_req__baselibs__maintainable_design + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__base_libraries, stkh_req__overall_goals__reuse_of_app_soft + :status: valid + + The base libraries shall be designed for maintainability and code reuse. diff --git a/docs/features/baselibs/index.rst b/docs/features/baselibs/index.rst new file mode 100644 index 0000000000..f9f2861f13 --- /dev/null +++ b/docs/features/baselibs/index.rst @@ -0,0 +1,147 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _baselibs_feature: + +Base Libraries +############## + +.. document:: Base Libraries + :id: doc__baselibs + :status: valid + :safety: ASIL_B + :tags: feature_request + + +.. toctree:: + :hidden: + + docs/requirements/index.rst + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_baselibs`` + +Abstract +======== + +This feature provides a set of base libraries for both C++ and Rust that can be used by S-CORE +components. +These libraries offer common functionality, ensuring consistent implementations, reducing code +duplication, and promoting interoperability between components. + +The base libraries include utilities for bit manipulation, concurrency management, containers, +JSON processing, filesystem operations, memory handling, OS abstraction, error handling, +serialization, logging, and various other common utilities needed across the S-CORE system. + +Motivation +========== + +Base libraries are essential to ensure consistency, reduce code duplication, and improve quality +across S-CORE components. + +Rationale +========= + +A base library is developed only if it is required by at least two S-CORE components. +This ensures that the effort to create and maintain a base library is justified by real, +shared needs across the platform. + +Each base library may provide an API for Rust, C++, or both, depending on the requirements of +the consuming components. When possible, a library should be implemented once in either Rust +or C++ and provide bindings to the other language to maximize maintainability and consistency. +However, if there are strong technical reasons (such as language-specific performance or safety +requirements), a library may be implemented separately in both Rust and C++. + +Specification +============= + +The base libraries feature consists of the following libraries, all of which are currently implemented in C++: + +- **bitmanipulation**: Utilities for bit manipulation. +- **concurrency**: Provides a generic interface to execute any C++ callable in a parallel context, + supporting various execution strategies (e.g., thread pool, timed execution), thread safety, + interruption handling, and periodic/delayed task execution. +- **containers**: Offers a ``DynamicArray`` (fixed-size array with dynamic construction-time size) + and an intrusive linked list implementation conforming to the + `P0406R1 proposal `_. +- **json**: JSON abstraction layer that can switch between different parsers/serializers under the hood. +- **filesystem**: Filesystem manipulation library similar to ``std::filesystem``. +- **futurecpp**: Extends the C++14 Standard Library with features from newer C++ standards up to C++26, + as well as selected proposals for the C++ Standard Library. +- **safecpp/aborts_upon_exception**: Globally prevents creation of exception objects by calling ``std::abort()`` + immediately. +- **safecpp/coverage_termination_handler**: Helper library to enable collective code coverage information in + GTest death tests. +- **safecpp/safe_math**: Provides safe implementations for arithmetic and related operations for + signed/unsigned integral types and floating point types. +- **safecpp/scoped_function**: Allows developers to consciously limit when an enclosed callable + (function) can be invoked. +- **memory**: Utility library for memory handling, including an abstraction layer for shared memory. +- **os**: OS Abstraction Layer (OSAL) to interface with different POSIX-like operating systems such + as Linux and QNX. +- **result**: Provides a unified approach to error handling without exceptions, conforming to C++23 + ``std::expected``. +- **static_reflection_with_serialization**: A header-only library for binary serialization, + deserialization, and compile-time type reflection of heterogenuous C++ data structures with focus + on compile-time safety and efficiency of serialization, as well as efficiency of filtering by + content during deserialization. +- **mw::log**: Logging library. +- **utils**: Provides a collection of small, reusable utilities that do not fit into the other + base libraries. + +Backwards Compatibility +======================= + +As this is a new feature, there are no backwards compatibility concerns. + +Security Impact +=============== + +Base libraries present varying security risks as vulnerabilities could affect multiple components +simultaneously. +Each library requires individual security impact analysis based on its functionality and usage patterns. + +Safety Impact +============= + +- Due to wide usage of the base libraries throughout the platform, extra care is needed in design, + implementation, and testing to minimize safety impact. +- Libraries are developed at various integrity levels from QM (non-safety) up to ASIL-B, + depending on their intended use cases. + +License Impact +============== + +The base libraries are licensed under Apache License 2.0. + +How to Teach This +================= + +Each library is expected to have documentation that includes an API reference and usage examples +where necessary. + +Rejected Ideas +============== + +There are no rejected ideas related to the base libraries feature at this time. + +Open Issues +=========== + +There are currently no open issues related to the base libraries feature. diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 341111d729..e2af16a148 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -120,6 +120,17 @@ Functional requirements The platform shall support safe computation. +.. stkh_req:: Base Libraries + :id: stkh_req__functional_req__base_libraries + :reqtype: Functional + :security: NO + :safety: ASIL_B + :rationale: Common libraries reduce duplication, improve consistency and quality across components. + :status: valid + + The software platform shall provide a set of base libraries offering common functionality for platform components. + + .. stkh_req:: Hardware Accelerated Computation :id: stkh_req__functional_req__hardware_comput :reqtype: Functional From 1b143efec84bf0fd00f11afbc75d7178a37801a3 Mon Sep 17 00:00:00 2001 From: Andrey Babanin Date: Mon, 19 May 2025 17:04:39 +0200 Subject: [PATCH 006/102] docs: Add safety and security requirements for base libraries --- .../baselibs/docs/requirements/index.rst | 20 +++++++++++++++++++ docs/features/baselibs/index.rst | 2 +- docs/requirements/stakeholder/index.rst | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/features/baselibs/docs/requirements/index.rst b/docs/features/baselibs/docs/requirements/index.rst index e840f0be54..f8b783bd12 100644 --- a/docs/features/baselibs/docs/requirements/index.rst +++ b/docs/features/baselibs/docs/requirements/index.rst @@ -25,6 +25,16 @@ Requirements The base libraries shall include core software utilities and common infrastructure components needed by multiple platform modules. +.. feat_req:: Safety Relevance + :id: feat_req__baselibs__safety + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functional_req__base_libraries + :status: valid + + The base libraries shall implement functionality necessary to support safety-relevant platform components up to ASIL-B. + .. feat_req:: Multi-Language APIs :id: feat_req__baselibs__multi_language_apis :reqtype: Functional @@ -54,3 +64,13 @@ Requirements :status: valid The base libraries shall be designed for maintainability and code reuse. + +.. feat_req:: Security Robustness + :id: feat_req__baselibs__security + :reqtype: Non-Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__base_libraries + :status: valid + + The base libraries shall adhere to secure coding standards to prevent vulnerabilities across platform components. diff --git a/docs/features/baselibs/index.rst b/docs/features/baselibs/index.rst index f9f2861f13..e515c2ba4b 100644 --- a/docs/features/baselibs/index.rst +++ b/docs/features/baselibs/index.rst @@ -133,7 +133,7 @@ The base libraries are licensed under Apache License 2.0. How to Teach This ================= -Each library is expected to have documentation that includes an API reference and usage examples +Each library is expected to have a user manual that includes an API reference and usage examples where necessary. Rejected Ideas diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index e2af16a148..3e5571085e 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -123,7 +123,7 @@ Functional requirements .. stkh_req:: Base Libraries :id: stkh_req__functional_req__base_libraries :reqtype: Functional - :security: NO + :security: YES :safety: ASIL_B :rationale: Common libraries reduce duplication, improve consistency and quality across components. :status: valid From ee761978792cdfb7225581e08148f64cf8440496 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 23 May 2025 10:58:13 +0200 Subject: [PATCH 007/102] Update docs/features/diagnostics/index.rst Co-authored-by: St. Muench Signed-off-by: Tim Kliefoth --- docs/features/diagnostics/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index de27828096..705f780abe 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -146,7 +146,7 @@ UDS2SOVD Proxy - Exposes selected SOVD functionality via UDS for backward-compatible testers. - Acts as a local translation layer between UDS clients and SOVD stack. -- Configured using a ODX to define what is exposed. +- Configured via ODX files to define what is exposed. Out of scope components From f74a0a08ad31bf9fe4ce04abd1d10bee75140cd1 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 23 May 2025 15:46:04 +0200 Subject: [PATCH 008/102] Apply suggestions from code review Co-authored-by: St. Muench Signed-off-by: Tim Kliefoth --- docs/features/diagnostics/index.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 705f780abe..31a9849709 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -121,19 +121,19 @@ SOVD Server Service App -- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g., DTC clear, ECU reset, Flash Master). +- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). - Interfaces with the SOVD Server via IPC. SOVD Gateway -- Forwards SOVD requests to appropriate backend targets (e.g., adapters, proxies, clients). +- Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). - Acts as a router between clients and distributed SOVD components. - Supports multi-ECU SOVD communication. SOVD Client - Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. -- Can be used by developers, testers, ECUs or cloud services- should be deployment agnostic. +- Can be used by developers, testers, ECUs or cloud services; should be deployment agnostic. - Handles access control on the client side – e.g. by providing relevant certificates. Classic Diagnostic Adapter @@ -153,7 +153,7 @@ Out of scope components ----------------------- The following components are out of scope for this feature request but are included for context. -Each is briefly described to illustrate its role within the overall system architecture and +Each one is briefly described to illustrate its role within the overall system architecture and to highlight any resulting requirements or constraints imposed by the diagnostic system design. Logging @@ -162,7 +162,7 @@ Logging Configuration Manager -- Provides configuration data to the SOVD Server (e.g., ECU layout, variant, parameters). +- Provides configuration data to the SOVD Server (e.g. ECU layout, variant, parameters). - Enables parametrization of applications. Authentication Manager @@ -240,14 +240,14 @@ Backwards Compatibility ======================= UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. -ODX as a standardized exchange format further ensure compatibility with proprietary diagnostic data models. +ODX as a standardized exchange format further ensures compatibility with proprietary diagnostic data models. Security Impact =============== The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. -Diagnostics inherently allow access to system information, state manipulation, coding, and software updates—all of which pose risks if accessed by unauthorized actors. +Diagnostics inherently allow access to system information, state manipulation, coding, and software updates - all of which pose risks if accessed by unauthorized actors. SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. @@ -272,8 +272,8 @@ License Impact ============== There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. -While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts—especially Part 3, -which defines the API—are already publicly available for purchase as Draft International Standards (DIS). +While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts - especially Part 3, +which defines the API - are already publicly available for purchase as Draft International Standards (DIS). These drafts are considered stable and are typically subject only to minor editorial changes before final publication. As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. From 8014655ca22045c7c652a7fc4b88992755df766d Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 23 May 2025 16:02:56 +0200 Subject: [PATCH 009/102] updates from feedback --- .../_assets/score-diagnostics-draft.drawio.svg | 14 +++++++------- docs/features/diagnostics/index.rst | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg index 37c605ec8a..d3f9b29206 100644 --- a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg +++ b/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg @@ -1,4 +1,4 @@ - + @@ -1047,13 +1047,13 @@
- F lib + Fault lib
- F lib + Fault lib @@ -1089,13 +1089,13 @@
- F lib + Fault lib
- F lib + Fault lib @@ -1174,13 +1174,13 @@
- F lib + Fault lib
- F lib + Fault lib diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 31a9849709..8dc9b7c1d2 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -87,21 +87,21 @@ In scope components The following components are considered in scope of this feature request. -F lib (Fault Library) +Fault Library - Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. - Relays faults via IPC to central Diagnostic Fault Manager. - Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface - Reporting of faults additionally results in a log entry. - The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. -- F lib is the base for activity specific, custom fault handling. +- Fault lib is the base for activity specific, custom fault handling. Diagnostic Fault Manager -- Aggregates and manages diagnostic fault data from F libs across the system. +- Aggregates and manages diagnostic fault data from Fault libs across the system. - Provides centralized fault status to the SOVD Server. - Interfaces with the Diagnostic DB (persistency) to store and retrieve data. -- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by F libs. +- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. Diagnostic DB From a52d6d7db3c7229a3a02c0b426c00ea42c0d4e13 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 6 Jun 2025 09:46:39 +0200 Subject: [PATCH 010/102] updated structure and addressed feedback restructured to add requirements as a seperate file addressed feedback from workshop like open points and central vs decentral indication --- .../score-diagnostics-draft.drawio.svg | 0 docs/features/diagnostics/design/index.rst | 295 +++++++++++++++++ docs/features/diagnostics/index.rst | 304 +----------------- .../diagnostics/requirements/index.rst | 51 +++ 4 files changed, 354 insertions(+), 296 deletions(-) rename docs/features/diagnostics/{ => design}/_assets/score-diagnostics-draft.drawio.svg (100%) create mode 100644 docs/features/diagnostics/design/index.rst create mode 100644 docs/features/diagnostics/requirements/index.rst diff --git a/docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg b/docs/features/diagnostics/design/_assets/score-diagnostics-draft.drawio.svg similarity index 100% rename from docs/features/diagnostics/_assets/score-diagnostics-draft.drawio.svg rename to docs/features/diagnostics/design/_assets/score-diagnostics-draft.drawio.svg diff --git a/docs/features/diagnostics/design/index.rst b/docs/features/diagnostics/design/index.rst new file mode 100644 index 0000000000..e8d5270fb2 --- /dev/null +++ b/docs/features/diagnostics/design/index.rst @@ -0,0 +1,295 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _diagnostics_feature: + +Diagnostic and Fault Management +############################### + +.. document:: Diagnostics + :id: doc__diagnostics + :status: draft + :safety: QM + :tags: feature_request + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_diagnostics`` + + +Abstract +======== + +We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. +SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, +eliminating the need for manually modeling diagnostic interfaces as required in UDS. +This significantly reduces integration overhead and simplifies the onboarding of new ECUs. +Additionally, SOVD enables scalable, secure, and cloud-ready diagnostics with real-time fault access and +advanced data handling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, +improve system maintainability, and support future-proof diagnostic workflows. + +The intent of this feature request is to define a high-level architecture for the diagnostic system. +The components listed throughout this document require detailed feature requests in the future respectively. + + +Motivation +========== + +Currently there is no solution for vehicle diagnostics in S-CORE. +Diagnostic is a core capability of automotive platform stacks and is required for various use-cases +such as field troubleshooting, quality assurance, after sales, production, development and more. + + +Rationale +========= + +SOVD was chosen as the foundation for the diagnostic architecture because it offers a modern, +service-oriented approach that aligns with the industry's shift toward Ethernet-based communication and scalable software-defined vehicle platforms. +It provides a standardized and extensible interface that enables better interoperability across ECUs, testers, and external tools. + + +Specification +============= + + +Architecture +------------ + +The proposed concept consists of three main parts: + +1. A framework agnostic library to aggregate faults and integrate the diagnostic system into S-CORE +2. A SOVD based diagnostic system +3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs + +The diagram below shows the entire concept with the three subgroups connected. + +.. image:: _assets/score-diagnostics-draft.drawio.svg + :alt: Diagnostic stack component architecture + + +In scope components +------------------- + +The following components are considered in scope of this feature request. + +Fault Library + +- Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. +- Relays faults via IPC to central Diagnostic Fault Manager. +- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface +- Reporting of faults additionally results in a log entry. +- The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. +- Fault lib is the base for activity specific, custom fault handling. +- Can and should also be used by platform components to report faults. +- Decentral component. + +Diagnostic Fault Manager + +- Aggregates and manages diagnostic fault data from Fault libs across the system. +- Provides centralized fault status to the SOVD Server. +- Interfaces with the Diagnostic DB (persistency) to store and retrieve data. +- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. +- Central component. + +Diagnostic DB + +- Stores static and runtime diagnostic data +- Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. +- The data format needs to be specified further but will likely include: +- Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. +- Fault ID (FID): ECU specific ID to uniquely identify every fault. +- Count: occurrence count of DTC/fault. +- Meta data: meta data related to fault occurrence. +- Central component. + +SOVD Server + +- Central entry point for all diagnostic requests via SOVD. +- Implements the SOVD API and dispatches requests to services, DB, and fault manager. +- Manages authentication, configuration, and data access via IPC. +- Central component. + +Service App + +- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). +- Interfaces with the SOVD Server via IPC. +- Central component derived from base service app. + +SOVD Gateway + +- Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). +- Acts as a router between clients and distributed SOVD components. +- Supports multi-ECU SOVD communication. +- Central component. + +SOVD Client + +- Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. +- Can be used by developers, testers, ECUs or cloud services; should be deployment agnostic. +- Handles access control on the client side – e.g. by providing relevant certificates. +- Central component - but could be deployed mutliple times (e.g. one on-baord and one off-baord). + +Classic Diagnostic Adapter + +- Translates SOVD service calls to UDS commands. +- Enables backward compatibility with legacy ECUs that only support UDS. +- Configured via ODX files describing ECU-specific UDS expectations. +- Central component. + +UDS2SOVD Proxy + +- Exposes selected SOVD functionality via UDS for backward-compatible testers. +- Acts as a local translation layer between UDS clients and SOVD stack. +- Configured via ODX files to define what is exposed. +- Central component. + + +Out of scope components +----------------------- + +The following components are out of scope for this feature request but are included for context. +Each one is briefly described to illustrate its role within the overall system architecture and +to highlight any resulting requirements or constraints imposed by the diagnostic system design. + +Logging + +- Enables the Fault Library to log fault events. +- All SOVD components can interact with logging. + +Configuration Manager + +- Provides configuration data to the SOVD Server (e.g. ECU layout, variant, parameters). +- Enables parametrization of applications. + +Authentication Manager + +- Manages authentication and authorization for incoming SOVD requests. +- Ensures only valid users or clients can access services. + +Crypto + +- Provides cryptographic services – e.g. securely store and retrieve diagnostic certificates. +- Used by Authentication Manager. + +Persistency + +- Provides persistent data storage. + +Flash Service App + +- Specialized extension of the Service App to handle ECU flashing. +- Provides routines for software update/bootloader access via diagnostics. + +Rest of Vehicle UDS + +- Represents legacy ECUs in the vehicle that only speak UDS. +- Interact via the Classic Diagnostic Adapter (SOVD2UDS). + +Rest of Vehicle SOVD + +- Other ECUs in the vehicle that already support SOVD natively. +- Can communicate directly with the SOVD Gateway. + +UDS Tester + +- Traditional diagnostics tester that uses UDS protocol. +- Communicates with the UDS2SOVD Proxy for limited diagnostics access. + + +Requirements +------------ + +The related requirements can be found in :doc:`../requirements/index`. + + +Backwards Compatibility +======================= + +UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. +ODX as a standardized exchange format further ensures compatibility with proprietary diagnostic data models. + + +Security Impact +=============== + +The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. +Diagnostics inherently allow access to system information, state manipulation, coding, and software updates - all of which pose risks if accessed by unauthorized actors. +SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, +but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. +If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. +This may enable new threat scenarios and attack paths, particularly over external or less trusted networks. +To mitigate these risks, the diagnostic stack shall enforce secure communication via HTTPS, +authenticate endpoints using certificates (see architecture diagram), and implement strict access control mechanisms. +While diagnostics do not directly impact functional safety, a successful attack could indirectly influence safety-relevant functions +- for example by setting the system into a different state. +Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. + + +Safety Impact +============= + +At this point in time no direct safety impact is foreseen. The expected ASIL level is QM. +Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. +As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions +- for example by setting the system into a different state. + + +License Impact +============== + +There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. +While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts - especially Part 3, +which defines the API - are already publicly available for purchase as Draft International Standards (DIS). +These drafts are considered stable and are typically subject only to minor editorial changes before final publication. +As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. +Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. + +The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. + + +How to Teach This +================= + +A good starting point to get an overview of SOVD is the overview pages provided by ISO [#s1]_ and ASAM [#s2]_. + + +Rejected Ideas +============== + +An UDS first based diagnostic system was considered but rejected. +The current market trend clearly indicates the move towards SOVD. +Additionally, there a multiple well established proprietary UDS stacks and tools available. +Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CORE to provide value and increase adoption. + + +Open Issues +=========== + +- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase +- Investigate synergies between Configuration Manager and Diagnostic Fault Manager +- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 +- Check if Diagnostic Fault Manager component is required at all and could be removed (how would this impact dependency of Flib to persistency and access management?) +- Provide sequence diagram for a use case +- Provide requirements + + +Footnotes +========= + +.. [#s1] "SOVD Standard ISO/DIS 17978", ISO, https://www.iso.org/standard/85133.html. +.. [#s2] "ASAM SOVD Overview", ASAM, https://www.asam.net/standards/detail/sovd. diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 8dc9b7c1d2..a3a5c61beb 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -1,6 +1,6 @@ .. # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation + # Copyright (c) 2024 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,300 +12,12 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _diagnostics_feature: +Diagnostics +########### -Diagnostic and Fault Management -############################### +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: -.. document:: Diagnostics - :id: doc__diagnostics - :status: draft - :safety: QM - :tags: feature_request - - -Feature flag -============ - -To activate this feature, use the following feature flag: - -``experimental_diagnostics`` - - -Abstract -======== - -We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. -SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, -eliminating the need for manually modeling diagnostic interfaces as required in UDS. -This significantly reduces integration overhead and simplifies the onboarding of new ECUs. -Additionally, SOVD enables scalable, secure, and cloud-ready diagnostics with real-time fault access and -advanced data handling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, -improve system maintainability, and support future-proof diagnostic workflows. - -The intent of this feature request is to define a high-level architecture for the diagnostic system. -The components listed throughout this document require detailed feature requests in the future respectively. - - -Motivation -========== - -Currently there is no solution for vehicle diagnostics in S-CORE. -Diagnostic is a core capability of automotive platform stacks and is required for various use-cases -such as field troubleshooting, quality assurance, after sales, production, development and more. - - -Rationale -========= - -SOVD was chosen as the foundation for the diagnostic architecture because it offers a modern, -service-oriented approach that aligns with the industry's shift toward Ethernet-based communication and scalable software-defined vehicle platforms. -It provides a standardized and extensible interface that enables better interoperability across ECUs, testers, and external tools. - - -Specification -============= - - -Architecture ------------- - -The proposed concept consists of three main parts: - -1. A framework agnostic library to aggregate faults and integrate the diagnostic system into S-CORE -2. A SOVD based diagnostic system -3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs - -The diagram below shows the entire concept with the three subgroups connected. - -.. image:: _assets/score-diagnostics-draft.drawio.svg - :alt: Diagnostic stack component architecture - - -In scope components -------------------- - -The following components are considered in scope of this feature request. - -Fault Library - -- Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. -- Relays faults via IPC to central Diagnostic Fault Manager. -- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface -- Reporting of faults additionally results in a log entry. -- The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. -- Fault lib is the base for activity specific, custom fault handling. - -Diagnostic Fault Manager - -- Aggregates and manages diagnostic fault data from Fault libs across the system. -- Provides centralized fault status to the SOVD Server. -- Interfaces with the Diagnostic DB (persistency) to store and retrieve data. -- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. - -Diagnostic DB - -- Stores static and runtime diagnostic data -- Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. -- The data format needs to be specified further but will likely include: -- Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. -- Fault ID (FID): ECU specific ID to uniquely identify every fault. -- Count: occurrence count of DTC/fault. -- Meta data: meta data related to fault occurrence. - -SOVD Server - -- Central entry point for all diagnostic requests via SOVD. -- Implements the SOVD API and dispatches requests to services, DB, and fault manager. -- Manages authentication, configuration, and data access via IPC. - -Service App - -- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). -- Interfaces with the SOVD Server via IPC. - -SOVD Gateway - -- Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). -- Acts as a router between clients and distributed SOVD components. -- Supports multi-ECU SOVD communication. - -SOVD Client - -- Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. -- Can be used by developers, testers, ECUs or cloud services; should be deployment agnostic. -- Handles access control on the client side – e.g. by providing relevant certificates. - -Classic Diagnostic Adapter - -- Translates SOVD service calls to UDS commands. -- Enables backward compatibility with legacy ECUs that only support UDS. -- Configured via ODX files describing ECU-specific UDS expectations. - -UDS2SOVD Proxy - -- Exposes selected SOVD functionality via UDS for backward-compatible testers. -- Acts as a local translation layer between UDS clients and SOVD stack. -- Configured via ODX files to define what is exposed. - - -Out of scope components ------------------------ - -The following components are out of scope for this feature request but are included for context. -Each one is briefly described to illustrate its role within the overall system architecture and -to highlight any resulting requirements or constraints imposed by the diagnostic system design. - -Logging - -- Enables the Fault Library to log fault events. - -Configuration Manager - -- Provides configuration data to the SOVD Server (e.g. ECU layout, variant, parameters). -- Enables parametrization of applications. - -Authentication Manager - -- Manages authentication and authorization for incoming SOVD requests. -- Ensures only valid users or clients can access services. - -Crypto - -- Provides cryptographic services – e.g. securely store and retrieve diagnostic certificates. -- Used by Authentication Manager. - -Persistency - -- Provides persistent data storage. - -Flash Service App - -- Specialized extension of the Service App to handle ECU flashing. -- Provides routines for software update/bootloader access via diagnostics. - -Rest of Vehicle UDS - -- Represents legacy ECUs in the vehicle that only speak UDS. -- Interact via the Classic Diagnostic Adapter (SOVD2UDS). - -Rest of Vehicle SOVD - -- Other ECUs in the vehicle that already support SOVD natively. -- Can communicate directly with the SOVD Gateway. - -UDS Tester - -- Traditional diagnostics tester that uses UDS protocol. -- Communicates with the UDS2SOVD Proxy for limited diagnostics access. - - -Requirements ------------- - -The following section includes unordered and incomplete feature requirements. - -.. feat_req:: SOVD Standard - :id: feat_req__diagnostics__sovd_std - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd - :status: valid - - The SOVD implementation shall conform to the SOVD standard as defined in ISO/DIS 17978 (or the latest available draft or final publication). - -.. feat_req:: OEM Diagnostic Plug In - :id: feat_req__diagnostics__oem_plugin - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd - :status: valid - - The diagnostic system shall provide a plug-in mechanism to include OEM-specific features. - -.. feat_req:: Diagnostic system internal communication - :id: feat_req__diagnostics__internal_com - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd - :status: valid - - All internal communication between diagnostic components that do not use UDS or SOVD protocols shall be implemented using the S-CORE::COM middleware. - - -Backwards Compatibility -======================= - -UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. -ODX as a standardized exchange format further ensures compatibility with proprietary diagnostic data models. - - -Security Impact -=============== - -The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. -Diagnostics inherently allow access to system information, state manipulation, coding, and software updates - all of which pose risks if accessed by unauthorized actors. -SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, -but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. -If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. -This may enable new threat scenarios and attack paths, particularly over external or less trusted networks. -To mitigate these risks, the diagnostic stack shall enforce secure communication via HTTPS, -authenticate endpoints using certificates (see architecture diagram), and implement strict access control mechanisms. -While diagnostics do not directly impact functional safety, a successful attack could indirectly influence safety-relevant functions -- for example by setting the system into a different state. -Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. - - -Safety Impact -============= - -At this point in time no direct safety impact is foreseen. The expected ASIL level is QM. -Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. -As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions -- for example by setting the system into a different state. - - -License Impact -============== - -There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. -While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts - especially Part 3, -which defines the API - are already publicly available for purchase as Draft International Standards (DIS). -These drafts are considered stable and are typically subject only to minor editorial changes before final publication. -As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. -Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. - -The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. - - -How to Teach This -================= - -A good starting point to get an overview of SOVD is the overview pages provided by ISO [#s1]_ and ASAM [#s2]_. - - -Rejected Ideas -============== - -An UDS first based diagnostic system was considered but rejected. -The current market trend clearly indicates the move towards SOVD. -Additionally, there a multiple well established proprietary UDS stacks and tools available. -Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CORE to provide value and increase adoption. - - -Open Issues -=========== - -- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase -- Investigate synergies between Configuration Manager and central diagnostic configuration file in Diagnostic Fault Manager -- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 - - -Footnotes -========= - -.. [#s1] "SOVD Standard ISO/DIS 17978", ISO, https://www.iso.org/standard/85133.html. -.. [#s2] "ASAM SOVD Overview", ASAM, https://www.asam.net/standards/detail/sovd. + */index diff --git a/docs/features/diagnostics/requirements/index.rst b/docs/features/diagnostics/requirements/index.rst new file mode 100644 index 0000000000..3bdac7a65a --- /dev/null +++ b/docs/features/diagnostics/requirements/index.rst @@ -0,0 +1,51 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Requirements +############ + +Diagnostic and Fault Management +=============================== + + +.. feat_req:: SOVD Standard + :id: feat_req__diagnostics__sovd_std + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The SOVD implementation shall conform to the SOVD standard as defined in ISO/DIS 17978 (or the latest available draft or final publication). + +.. feat_req:: OEM Diagnostic Plug In + :id: feat_req__diagnostics__oem_plugin + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The diagnostic system shall provide a plug-in mechanism to include OEM-specific features. + +.. feat_req:: Diagnostic system internal communication + :id: feat_req__diagnostics__internal_com + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__dtc_read_sovd + :status: valid + + All internal communication between diagnostic components that do not use UDS or SOVD protocols shall be implemented using the S-CORE::COM middleware. From abc80a61f985c6e012c56cf99f43c8a32288d328 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 6 Jun 2025 10:41:19 +0200 Subject: [PATCH 011/102] added diagram distributed view distributed view shoes component deployment in system --- .../score-diagnostics-distributed.drawio.svg | 1399 +++++++++++++++++ ...rawio.svg => score-diagnostics.drawio.svg} | 0 docs/features/diagnostics/design/index.rst | 15 +- 3 files changed, 1409 insertions(+), 5 deletions(-) create mode 100644 docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg rename docs/features/diagnostics/design/_assets/{score-diagnostics-draft.drawio.svg => score-diagnostics.drawio.svg} (100%) diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg b/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg new file mode 100644 index 0000000000..87baeb6c71 --- /dev/null +++ b/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg @@ -0,0 +1,1399 @@ + + + + + + + + + + + + +
+
+
+ HPC1 +
+
+
+
+ + HPC1 + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ Diagnostic Fault Manager +
+
+
+
+ + Diagnostic Fault Man... + +
+
+
+ + + + + + + + +
+
+
+ Diagnostic DB +
+
+
+
+ + Diagnostic... + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ Fault lib +
+
+
+
+ + Fault lib + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ SOVD Server +
+
+
+
+ + SOVD Server + +
+
+
+ + + + + + + +
+
+
+ Service App +
+
+
+
+ + Service App + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ SOVD Gateway +
+
+
+
+ + SOVD Gateway + +
+
+
+ + + + + + + +
+
+
+ Classic Diagnostic +
+ Adapter +
+
+
+
+
+ + Classic Diagnostic... + +
+
+
+ + + + + + + +
+
+
+ UDS2SOVD +
+ Proxy +
+
+
+
+
+ + UDS2SOVD... + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ DRAFT: S-CORE Diagnostic & Fault Management Stack - Distributed View +
+
+
+
+ + DRAFT: S... + +
+
+
+ + + + + + + +
+
+
+ SOVD Client (offboard, onboard, cloud) +
+
+
+
+ + SOVD Client (offboar... + +
+
+
+ + + + + + + +
+
+
+ UDS Tester +
+
+
+
+ + UDS Tester + +
+
+
+ + + + + + + + + +
+
+
+ HPC2 +
+
+
+
+ + HPC2 + +
+
+
+ + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ Diagnostic Fault Manager +
+
+
+
+ + Diagnostic Fault Man... + +
+
+
+ + + + + + + + +
+
+
+ Diagnostic DB +
+
+
+
+ + Diagnostic... + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ Fault lib +
+
+
+
+ + Fault lib + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ SOVD Server +
+
+
+
+ + SOVD Server + +
+
+
+ + + + + + + +
+
+
+ Service App +
+
+
+
+ + Service App + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + + + +
+
+
+ IPC +
+
+
+
+ + IPC + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + +
+
+
+ 1 +
+
+
+
+ + 1 + +
+
+
+ + + + + + + + + +
+
+
+ MCU1 +
+
+
+
+ + MCU1 + +
+
+
+ + + + + + + + + +
+
+
+ UDS +
+
+
+
+ + UDS + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + + + +
+
+
+ UDS +
+
+
+
+ + UDS + +
+
+
+ + + + + + + + + +
+
+
+ SOVD +
+
+
+
+ + SOVD + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+ + + + + + + +
+
+
+ * +
+
+
+
+ + * + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics-draft.drawio.svg b/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg similarity index 100% rename from docs/features/diagnostics/design/_assets/score-diagnostics-draft.drawio.svg rename to docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg diff --git a/docs/features/diagnostics/design/index.rst b/docs/features/diagnostics/design/index.rst index e8d5270fb2..47a8b90d18 100644 --- a/docs/features/diagnostics/design/index.rst +++ b/docs/features/diagnostics/design/index.rst @@ -76,12 +76,17 @@ The proposed concept consists of three main parts: 2. A SOVD based diagnostic system 3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs -The diagram below shows the entire concept with the three subgroups connected. +The diagram below shows the concept with the three subgroups connected. -.. image:: _assets/score-diagnostics-draft.drawio.svg +.. image:: _assets/score-diagnostics.drawio.svg :alt: Diagnostic stack component architecture +The next diagram shows the concept in a distributed view to highlight components that are unique per system or per device. + +.. image:: _assets/score-diagnostics.drawio.svg + :alt: Diagnostic stack component architecture + In scope components ------------------- @@ -135,7 +140,7 @@ SOVD Gateway - Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). - Acts as a router between clients and distributed SOVD components. - Supports multi-ECU SOVD communication. -- Central component. +- Central component and unique per system. SOVD Client @@ -149,14 +154,14 @@ Classic Diagnostic Adapter - Translates SOVD service calls to UDS commands. - Enables backward compatibility with legacy ECUs that only support UDS. - Configured via ODX files describing ECU-specific UDS expectations. -- Central component. +- Central component and unique per system. UDS2SOVD Proxy - Exposes selected SOVD functionality via UDS for backward-compatible testers. - Acts as a local translation layer between UDS clients and SOVD stack. - Configured via ODX files to define what is exposed. -- Central component. +- Central component and unique per system. Out of scope components From 4395de091361d80ca7817d9032059a7d63be71b2 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth Date: Fri, 6 Jun 2025 12:09:25 +0200 Subject: [PATCH 012/102] added requirements added feature and stakeholder requirements fixed typos --- .../score-diagnostics-distributed.drawio.svg | 38 ++-- .../_assets/score-diagnostics.drawio.svg | 12 +- docs/features/diagnostics/design/index.rst | 3 +- .../diagnostics/requirements/index.rst | 177 +++++++++++++++++- docs/requirements/stakeholder/index.rst | 97 ++++++++-- 5 files changed, 285 insertions(+), 42 deletions(-) diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg b/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg index 87baeb6c71..e3e334625f 100644 --- a/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg +++ b/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg @@ -1,4 +1,4 @@ - + @@ -747,13 +747,13 @@
- DRAFT: S-CORE Diagnostic & Fault Management Stack - Distributed View + S-CORE Diagnostic & Fault Management Stack - Distributed View
- DRAFT: S... + S-CORE D... @@ -1126,34 +1126,34 @@ - + -
+
- * + 1
- - * + + 1 - + -
+
1 @@ -1161,20 +1161,20 @@
- + 1 - + -
+
1 @@ -1182,29 +1182,29 @@
- + 1 - + -
+
- 1 + *
- - 1 + + * diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg b/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg index d3f9b29206..fff8c7394f 100644 --- a/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg +++ b/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg @@ -1,4 +1,4 @@ - + @@ -645,22 +645,22 @@ - + -
+
- DRAFT: S-CORE Diagnostic & Fault Management Stack + S-CORE Diagnostic & Fault Management Stack
- - DRAFT: S... + + S-CORE D... diff --git a/docs/features/diagnostics/design/index.rst b/docs/features/diagnostics/design/index.rst index 47a8b90d18..8f2236980d 100644 --- a/docs/features/diagnostics/design/index.rst +++ b/docs/features/diagnostics/design/index.rst @@ -84,7 +84,7 @@ The diagram below shows the concept with the three subgroups connected. The next diagram shows the concept in a distributed view to highlight components that are unique per system or per device. -.. image:: _assets/score-diagnostics.drawio.svg +.. image:: _assets/score-diagnostics-distributed.drawio.svg :alt: Diagnostic stack component architecture In scope components @@ -290,7 +290,6 @@ Open Issues - Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 - Check if Diagnostic Fault Manager component is required at all and could be removed (how would this impact dependency of Flib to persistency and access management?) - Provide sequence diagram for a use case -- Provide requirements Footnotes diff --git a/docs/features/diagnostics/requirements/index.rst b/docs/features/diagnostics/requirements/index.rst index 3bdac7a65a..8f12672900 100644 --- a/docs/features/diagnostics/requirements/index.rst +++ b/docs/features/diagnostics/requirements/index.rst @@ -19,33 +19,202 @@ Requirements Diagnostic and Fault Management =============================== - .. feat_req:: SOVD Standard :id: feat_req__diagnostics__sovd_std :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd + :satisfies: stkh_req__diagnostics__via_sovd :status: valid The SOVD implementation shall conform to the SOVD standard as defined in ISO/DIS 17978 (or the latest available draft or final publication). +.. feat_req:: SOVD Server + :id: feat_req__diagnostics__sovd_server + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__via_sovd, stkh_req__diagnostics__secure_access + :status: valid + + The diagnostic system shall include a central SOVD server that exposes diagnostic functionality via a standard REST interface, dispatches incoming requests to backend services, and enforces authentication and access control. + +.. feat_req:: SOVD Configuration + :id: feat_req__diagnostics__sovd_config + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__via_sovd + :status: valid + + The system shall provide configuration management for SOVD components, including protocol parameters and security settings. + +.. feat_req:: SOVD Server Configuration Integration + :id: feat_req__diagnostics__sovd_config_mgr + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__via_sovd + :status: valid + + The SOVD server shall integrate with the S-CORE Configuration Manager to support runtime access and modification of configuration data. + +.. feat_req:: SOVD Server Authentication Integration + :id: feat_req__diagnostics__sovd_auth_mgr + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__secure_access + :status: valid + + The SOVD server shall integrate with the S-CORE Authentication Manager to enforce access control and validate client credentials. + +.. feat_req:: SOVD Gateway + :id: feat_req__diagnostics__sovd_gateway + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__distributed_support + :status: valid + + The system shall include a SOVD gateway to route diagnostic requests between different network domains and protocols. + +.. feat_req:: SOVD Client + :id: feat_req__diagnostics__sovd_client + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__via_sovd, stkh_req__diagnostics__secure_access + :status: valid + + The system shall provide a SOVD client to allow external applications to communicate with the SOVD server. + +.. feat_req:: SOVD Client Deployment Core + :id: feat_req__diagnostics__sovd_client_core + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__via_sovd + :status: valid + + The SOVD client shall be designed as a reusable core component that can be deployed in off-board, on-board, or cloud environments. + +.. feat_req:: Diagnostic Service Application + :id: feat_req__diagnostics__service_app + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__custom_services + :status: valid + + The diagnostic system shall include a base service application (AKA routine) that is triggered from the SOVD Server and used to derive custom service applications. + .. feat_req:: OEM Diagnostic Plug In :id: feat_req__diagnostics__oem_plugin :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd + :satisfies: stkh_req__diagnostics__custom_services :status: valid The diagnostic system shall provide a plug-in mechanism to include OEM-specific features. +.. feat_req:: Diagnostic Fault Library + :id: feat_req__diagnostics__fault_lib + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__fault_reporting + :status: valid + + The system shall include a fault reporting library that provides an IPC-based interface for applications and platform components to report diagnostic faults, including metadata. + +.. feat_req:: Fault Library Debouncing + :id: feat_req__diagnostics__fault_lib_debounce + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__fault_reporting + :status: valid + + The fault library shall support configurable error debouncing. + +.. feat_req:: Diagnostic Fault Manager + :id: feat_req__diagnostics__fault_manager + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__fault_reporting, stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The system shall include a central diagnostic fault manager that aggregates data from fault libraries, provides fault status to the SOVD server, and interfaces with a persistent diagnostic database. + +.. feat_req:: Diagnostic Database + :id: feat_req__diagnostics__db + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__fault_reporting, stkh_req__diagnostics__dtc_read_sovd + :status: valid + + The system shall include a diagnostic database using the S-CORE::Persistency module to store DTCs, occurrence counts, and associated metadata for fault events. + +.. feat_req:: Diagnostic Database Persistence + :id: feat_req__diagnostics__db_persistence + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__fault_reporting + :status: valid + + The diagnostic database shall store all diagnostic data persistently using the S-CORE::Persistency infrastructure. + +.. feat_req:: Classic Diagnostic Adapter + :id: feat_req__diagnostics__classic_adapter + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__uds_ecus + :status: valid + + The system shall include a classic diagnostic adapter to translate SOVD requests into UDS commands. + +.. feat_req:: Classic Diagnostic Adapter ODX Configuration + :id: feat_req__diagnostics__classic_adapter_odx + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__uds_ecus + :status: valid + + The classic diagnostic adapter shall support configuration via ODX files that describe the UDS command mappings and behavior per ECU. + +.. feat_req:: UDS to SOVD Proxy + :id: feat_req__diagnostics__uds2sovd_proxy + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__uds_tester_compat + :status: valid + + The system shall include a proxy to translate UDS diagnostic requests to SOVD protocol requests. + +.. feat_req:: UDS2SOVD Proxy ODX Configuration + :id: feat_req__diagnostics__uds2sovd_odx + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__diagnostics__uds_tester_compat + :status: valid + + The UDS2SOVD proxy shall support configuration via standardized ODX files to define which SOVD services are exposed via the UDS interface. + .. feat_req:: Diagnostic system internal communication :id: feat_req__diagnostics__internal_com :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__diagnostics__dtc_read_sovd + :satisfies: stkh_req__diagnostics__via_sovd, stkh_req__diagnostics__dtc_read_sovd :status: valid All internal communication between diagnostic components that do not use UDS or SOVD protocols shall be implemented using the S-CORE::COM middleware. diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 7a69c721cf..0a66a2545b 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -210,16 +210,6 @@ Functional requirements * debugging * feature activation -.. stkh_req:: Readout DTCs via SOVD - :id: stkh_req__diagnostics__dtc_read_sovd - :reqtype: Functional - :security: YES - :safety: QM - :rationale: tbd - :status: valid - - The system shall provide users the ability to retrieve current Diagnostic Trouble Codes (DTCs) from the ECU via the SOVD protocol. - Dependability ------------- @@ -544,11 +534,96 @@ Communication :status: valid The following diagnostic protocols shall be supported - * UDS (ISO14229) Diagnostics + * SOVD (ISO 17978) + * UDS (ISO 14229) Diagnostics * Diagnostic trouble codes * Diagnostic jobs +Diagnostics and Fault Management +-------------------------------- + +.. stkh_req:: Diagnostic via SOVD + :id: stkh_req__diagnostics__via_sovd + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Enables modern, scalable diagnostics using a standard REST-based protocol to improve integration, interoperability, and maintainability. + :status: valid + + The system shall support vehicle diagnostics via the SOVD protocol as defined in ISO 17978, to allow scalable and secure diagnostic access. + +.. stkh_req:: Fault Reporting Infrastructure + :id: stkh_req__diagnostics__fault_reporting + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Enables applications and components to report faults in a structured, reusable, and system-wide accessible manner. + :status: valid + + The system shall support a reusable fault reporting infrastructure that enables applications and platform components to report, persist, and manage diagnostic fault information. + +.. stkh_req:: Readout DTCs via SOVD + :id: stkh_req__diagnostics__dtc_read_sovd + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Enables reading of Diagnostic Trouble Codes (DTCs) from the ECU for various use-cases like production or maintenance. + :status: valid + + The system shall provide users the ability to retrieve current Diagnostic Trouble Codes (DTCs) from the ECU via the SOVD protocol. + +.. stkh_req:: Extensibility of Diagnostic Services + :id: stkh_req__diagnostics__custom_services + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Enables OEMs and developers to implement system-specific or project-specific routines for diagnostic control and testing. + :status: valid + + The diagnostic system shall support extensibility mechanisms that allow integration of custom diagnostic services and routines via the SOVD interface. + +.. stkh_req:: Compatibility with UDS Testers + :id: stkh_req__diagnostics__uds_tester_compat + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Ensures continued usability of existing test infrastructure, avoiding costly replacement of legacy tools and ensuring fulfillment of legal requirements. + :status: valid + + The diagnostic system shall provide compatibility with UDS-based testers by offering a proxy to translate UDS requests into SOVD-compatible actions. + +.. stkh_req:: Compatibility with UDS ECUs + :id: stkh_req__diagnostics__uds_ecus + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Ensures continued operability of ECUs that are not SOVD-capable. + :status: valid + + The diagnostic system shall support integration with ECUs that use UDS by providing a compatibility adapter to translate SOVD requests to UDS commands. + +.. stkh_req:: Support for Distributed and Multi-ECU Diagnostics + :id: stkh_req__diagnostics__distributed_support + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Enables the system to operate in modern, distributed vehicle architectures where diagnostics span multiple ECUs and subsystems. + :status: valid + + The diagnostic system shall support distributed diagnostics across multiple ECUs and network segments, enabling routing and aggregation of diagnostic data. + +.. stkh_req:: Secure Access to Diagnostic Interfaces + :id: stkh_req__diagnostics__secure_access + :reqtype: Functional + :security: YES + :safety: QM + :rationale: Diagnostic access allows deep system introspection and manipulation, which must be protected against unauthorized use. + :status: valid + + The diagnostic system shall enforce secure access control for all diagnostic interfaces, including authentication, encryption, and role-based access enforcement. + + Hardware support ---------------- From 74b9c59653e6a76ab5dc8ff14d8ad840e0ccdeb5 Mon Sep 17 00:00:00 2001 From: Arvid Sievert Date: Fri, 6 Jun 2025 16:42:00 +0200 Subject: [PATCH 013/102] logging: implement logging feature request Add documentation for the logging feature request, including description, requirements, and glossary. Co-authored-by: Ulrich Huber Co-authored-by: Philipp Ahmann <2428012+pahmann@users.noreply.github.com> Co-authored-by: Paula Grosu Co-authored-by: simon-acc Co-authored-by: Raghavendra Maddikery rmaddikery Co-authored-by: Andrey Babanin <4og@users.noreply.github.com> --- docs/features/analysis-infra/index.rst | 5 +- .../logging/docs/architecture/.gitkeep | 0 .../analysis-infra/logging/docs/glossary.rst | 47 ++ .../logging/docs/requirements/.gitkeep | 0 .../docs/requirements/mw-fr_logging_req.rst | 490 ++++++++++++++++++ .../logging/docs/safety_analysis/.gitkeep | 0 .../logging/docs/safety_planning/.gitkeep | 0 .../logging/docs/verification/.gitkeep | 0 .../features/analysis-infra/logging/index.rst | 7 +- .../analysis-infra/logging/mw-fr_logging.rst | 208 ++++++++ .../logging/mw-fr_logging_DD_Input.rst_tmp | 44 ++ .../logging/mw-log-api/index.rst | 16 - .../logging/tests/integration-tests/.gitkeep | 0 .../console-output => tracing}/index.rst | 7 +- .../tracing/mw-fr_tracing.rst_tmp | 118 +++++ 15 files changed, 921 insertions(+), 21 deletions(-) create mode 100644 docs/features/analysis-infra/logging/docs/architecture/.gitkeep create mode 100644 docs/features/analysis-infra/logging/docs/glossary.rst create mode 100644 docs/features/analysis-infra/logging/docs/requirements/.gitkeep create mode 100644 docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst create mode 100644 docs/features/analysis-infra/logging/docs/safety_analysis/.gitkeep create mode 100644 docs/features/analysis-infra/logging/docs/safety_planning/.gitkeep create mode 100644 docs/features/analysis-infra/logging/docs/verification/.gitkeep create mode 100644 docs/features/analysis-infra/logging/mw-fr_logging.rst create mode 100644 docs/features/analysis-infra/logging/mw-fr_logging_DD_Input.rst_tmp delete mode 100644 docs/features/analysis-infra/logging/mw-log-api/index.rst create mode 100644 docs/features/analysis-infra/logging/tests/integration-tests/.gitkeep rename docs/features/analysis-infra/{logging/console-output => tracing}/index.rst (92%) create mode 100644 docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp diff --git a/docs/features/analysis-infra/index.rst b/docs/features/analysis-infra/index.rst index 5df68e8215..aa5fede9d2 100644 --- a/docs/features/analysis-infra/index.rst +++ b/docs/features/analysis-infra/index.rst @@ -16,4 +16,7 @@ Analysis Infrastructure ####################### .. toctree:: - logging/index.rst + :maxdepth: 2 + + ./logging/index + ./tracing/index diff --git a/docs/features/analysis-infra/logging/docs/architecture/.gitkeep b/docs/features/analysis-infra/logging/docs/architecture/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/docs/glossary.rst b/docs/features/analysis-infra/logging/docs/glossary.rst new file mode 100644 index 0000000000..90647d8db5 --- /dev/null +++ b/docs/features/analysis-infra/logging/docs/glossary.rst @@ -0,0 +1,47 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Glossary +######## +.. glossary:: + + logging node + ECU or Partition (real or virtual) which generates log messages + + DLT + Diagnostic Log and Trace + + framework + Framework is a structured and extensible foundation for developing specific types of functionality in this case, logging. It supplies a set of default behaviors and configurable options, allowing developers to tailor and extend its capabilities to meet their application and system need. + + platform + Platform is the execution environment on which S-Core runs. It includes, for example, hardware (HW), operating system (OS), ... + + component + Component is a S-Core component + + log level + Log Level is the severity of a log message, necessary to categorize logs based on their importance e.g., FATAL, ERROR, WARN, INFO, DEBUG, VERBOSE such as in DLT + + logging entity + SW entity which generates log messages + + logging entity identifier + unique identifier for the logging entity, e.g., ECU ID / application ID / context ID, similar to DLT. + + log storage strategy + strategy to write/sync the cached log messages in the log storage location e.g., on system shutdown, on each message, on demand, on file size, on cache size, with circular or linear buffer + + QoS + Quality of Service diff --git a/docs/features/analysis-infra/logging/docs/requirements/.gitkeep b/docs/features/analysis-infra/logging/docs/requirements/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst b/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst new file mode 100644 index 0000000000..b135665722 --- /dev/null +++ b/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst @@ -0,0 +1,490 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + + +Requirements +############ + + + +.. feat_req:: Timestamping - Local Timestamp + :id: feat_req__logging__timestamping_local + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support local timestamps for each log entry. + +.. feat_req:: Timestamping - Original Timestamp + :id: feat_req__logging__timestamping_original + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support original timestamps for routed log entries. + +.. feat_req:: Timestamping - Timestamp Synchronization + :id: feat_req__logging__timestamping_sync + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support timestamp synchronization for log entries coming from different :term:`logging nodes `. + +.. feat_req:: Log Severity Levels + :id: feat_req__logging__severity_levels + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging framework shall support a log level for each log entry. + +.. feat_req:: Log Prioritization + :id: feat_req__logging__prioritization + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging framework shall prioritize logs in case of resource conflicts to ensure critical logs are not lost. + +.. feat_req:: Logging of Early Startup Events + :id: feat_req__logging__early_startup + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support logging of early startup events to capture critical initialization information. + +.. feat_req:: Log entity Identifier + :id: feat_req__logging__entity_identifier + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support :term:`logging entity identifiers` for each log entry. + +.. feat_req:: Log Filtering - Log Levels + :id: feat_req__logging__filtering_log_levels + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support filtering by :term:`log levels `. + +.. feat_req:: Log Filtering - Logging Entity ID + :id: feat_req__logging__filtering_entity_id + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support filtering by :term:`logging entity identifiers`. + +.. feat_req:: Message Loss Detection - Detection and Reporting + :id: feat_req__logging__message_loss_detection + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall detect and report any message loss. + +.. feat_req:: Message Loss Detection - Graceful Handling + :id: feat_req__logging__message_loss_handling + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall provide mechanisms to handle message loss gracefully. + + Additional Information: e.g. buffering or prioritizing critical messages + +.. feat_req:: Context-Specific Log Level Activation + :id: feat_req__logging__context_log_level + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow context-specific :term:`log level` activation at runtime to enable fine-grained control over logging behavior. + +.. feat_req:: Log Sources - User Application + :id: feat_req__logging__log_sources_user_app + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support user application as log source. + +.. feat_req:: Log Sources - Component and Platform + :id: feat_req__logging__log_sources + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support :term:`component` features and :term:` platform` as log sources. + +.. feat_req:: Log Sinks - Console + :id: feat_req__logging__log_sinks_console + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support console as a log sink. + +.. feat_req:: Log Sinks - Local File System + :id: feat_req__logging__log_sinks_local_fs + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support local file system as log sink. + + + +.. feat_req:: Log Sinks - Cloud Native Drive + :id: feat_req__logging__log_sinks_cloud_drive + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support cloud-native drives via network as log sinks. + +.. feat_req:: Log Sinks - Network + :id: feat_req__logging__log_sinks_network + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support network channels, including a second dedicated Ethernet channel, as log sinks. + +.. feat_req:: Log Sinks - Stdout for Unit Tests + :id: feat_req__logging__log_sinks_stdout + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall ensure logs appear on stdout when running unit tests. + +.. feat_req:: Previous boot logging + :id: feat_req__logging__boot_logging + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__boot_logging + :status: valid + + The logging :term:`framework` shall support logging of data to memory which survives a reboot + cycle. + +.. feat_req:: Configuration - Log Level + :id: feat_req__logging__config_log_level + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support configuration of :term:`log levels `. + +.. feat_req:: Log Sinks - Storage Device + :id: feat_req__logging__sink_device + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support configuration of the log storage device. + +.. feat_req:: Log Sinks - multiple Storage Device + :id: feat_req__logging__sink_multiple_device + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support multiple log storage devices. + +.. feat_req:: Log Sinks - Storage Strategy + :id: feat_req__logging__sink_strategy + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support configurable :term:`log storage strategy`. + +.. feat_req:: Configuration - Buffer Size + :id: feat_req__logging__config_buffer_size + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow configuration of internal buffers sizes. + +.. feat_req:: Configuration - Storage Size + :id: feat_req__logging__config_storage_size + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow configuration of storage size per log file. + +.. feat_req:: Configuration - Permission Settings + :id: feat_req__logging__config_permissions + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow configuration of permission settings for log access. + +.. feat_req:: Configuration - Log Filter + :id: feat_req__logging__config_log_filter + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow configuration of log filters. + +.. feat_req:: Configuration - Logging Entity ID + :id: feat_req__logging__config_entity_id + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow configuration of logging entity IDs. + +.. feat_req:: Configuration - On-Demand Functionality + :id: feat_req__logging__config_on_demand + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support on-demand functionality, such as enabling or disabling log storage. + +.. feat_req:: Configuration - Fallback Configurations + :id: feat_req__logging__config_fallback + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall provide fallback configurations, such as application-wide or system-wide defaults. + +.. feat_req:: Configuration - Custom Types Extension + :id: feat_req__logging__config_custom_types + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall allow extensions for custom log types. + +.. feat_req:: Error Handling - Recoverable Errors + :id: feat_req__logging__error_handling_recoverable + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + In case of recoverable error, the logging :term:`framework` shall continue the current operations. + +.. feat_req:: Error Handling - Non-Recoverable Errors + :id: feat_req__log__err_handling_nonrec + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + In case of non-recoverable error, the logging :term:`framework` shall deactivate silently and set an error state reported on shutdown. + +.. feat_req:: Error Handling - Application Isolation + :id: feat_req__logging__error_handling_isolation + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall ensure that user applications are not affected by logging :term:`framework` errors. + +.. feat_req:: Compatibility - Supported Operating Systems + :id: feat_req__logging__compat_os + :reqtype: Interface + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall support QNX and Linux operating systems (encapsulated via OSAL). + +.. feat_req:: Compatibility - Supported Programming Languages + :id: feat_req__logging__compat_languages + :reqtype: Interface + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support, stkh_req__dev_experience__prog_languages + :status: valid + + The logging :term:`framework` shall support C++, Rust, and Python programming languages. + +.. feat_req:: Resource Consumption - Storage + :id: feat_req__logging__resource_storage + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall minimize storage resource consumption. + +.. feat_req:: Resource Consumption - Communication Channel + :id: feat_req__logging__resource_comm_channel + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall minimize communication channel resource consumption. + +.. feat_req:: Resource Consumption - Runtime Resources + :id: feat_req__logging__resource_runtime + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall minimize runtime resource consumption. + +.. feat_req:: Resource Consumption - Performance Impact + :id: feat_req__logging__resource_performance + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall have low impact on overall system performance. + +.. feat_req:: Quality of Service - Message Handling + :id: feat_req__logging__qos_message_handling + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall provide:term:` QoS` for handling overflows or dropping log messages. +.. ist "rovide QoS for handling overflows or dropping log messages." doppelt zu den loos detection req.? + +.. feat_req:: Compatibility - DLT Protocol + :id: feat_req__logging__compat_dlt + :reqtype: Interface + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support, stkh_req__overall_goals__enable_cooperation + :status: valid + + The logging :term:`framework` shall be :term:`DLT` compatible. + + Additional Information: support for DLT message format, sending and receiving DLT messages, and integration with existing DLT tools and infrastructure. + +.. feat_req:: Security - Log File Access + :id: feat_req__logging__security_log_access + :reqtype: Non-Functional + :security: YES + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support, stkh_req__dependability__security_features + :status: valid + + The logging :term:`framework` shall ensure that only authorized users can access log files. + +.. feat_req:: Safety - ASIL Level Support + :id: feat_req__logging__asil_support + :reqtype: Non-Functional + :security: NO + :safety: ASIL_D + :satisfies: stkh_req__functional_req__safe_comput + :status: valid + + The logging :term:`framework` shall support the ASIL level of the user function to ensure compliance with the safety requirements of the application. + + Additional Information: Freedom from interfernce must be guaranteed with regard to the calling components. + +.. feat_req:: Safety - System Classification + :id: feat_req__logging__system_class + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__logging_support + :status: valid + + The logging :term:`framework` shall be classified according to the overall system's safety concept if logging information is part of the verification strategy. diff --git a/docs/features/analysis-infra/logging/docs/safety_analysis/.gitkeep b/docs/features/analysis-infra/logging/docs/safety_analysis/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/docs/safety_planning/.gitkeep b/docs/features/analysis-infra/logging/docs/safety_planning/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/docs/verification/.gitkeep b/docs/features/analysis-infra/logging/docs/verification/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/index.rst b/docs/features/analysis-infra/logging/index.rst index c727b73c88..5cd3cb97c5 100644 --- a/docs/features/analysis-infra/logging/index.rst +++ b/docs/features/analysis-infra/logging/index.rst @@ -16,5 +16,8 @@ Logging ####### .. toctree:: - console-output/index.rst - mw-log-api/index.rst + :maxdepth: 1 + + ./mw-fr_logging.rst + ./docs/requirements/mw-fr_logging_req.rst + ./docs/glossary.rst diff --git a/docs/features/analysis-infra/logging/mw-fr_logging.rst b/docs/features/analysis-infra/logging/mw-fr_logging.rst new file mode 100644 index 0000000000..67cdd08662 --- /dev/null +++ b/docs/features/analysis-infra/logging/mw-fr_logging.rst @@ -0,0 +1,208 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Request +############### + +.. document:: doc__logging + :id: doc__logging + :status: draft + :safety: ASIL_B + :tags: feature_request + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_logging`` + +Abstract +======== + +This feature request proposes the development of a safe, efficient and robust logging framework within S-CORE. + + +Motivation +========== + +- currently no solution available in the score platform + +Rationale +========= + +Logging provides the possibility to understand the running system by capturing detailed information about system +events and application-level activities. + +Specification +============= + +[Describe the requirements, architecture of any new feature.] [or] +[Describe the change to requirements, architecture, implementation, process, documentation, infrastructure of any change request.] + +Functionality +------------- + +Logging has to support the following features: + +- Timestamping + + - local timestamp for each log entry + - original timestamp for routed log entries + - timestamp synchronization for log entries coming from different logging nodes- + +- Log severity levels +- Log prioritization in case of resource conflicts +- logging of early startup events +- Log filtering + + - Support application and context identifier like in DLT + - Filtering by log levels for components and application level + - Out of scope "time" (tooling topic) + - logs filtering by logging entity ID (e.g., ECU ID, Application ID, Context ID such as in DLT) + - logs filtering by log level (e.g., FATAL, ERROR, WARN, INFO, DEBUG, VERBOSE such as in DLT) + + .. - Filtering options: it should have filter on app id and more fine-tuned filters on context ids. + +- message loss detection + + - optional functionality for logging. Important for tracing. + - Message loss detection + + - The logging framework must detect and report any message loss. + - It should provide mechanisms to handle message loss gracefully, such as buffering or prioritizing critical messages. + - The log consumer must be informed about any message loss to ensure the trustworthiness of the logs. + - would become mandatory in case verification is done via logging feature (not recommended) + +- Context specific log level activation at runtime + +Log Sources +----------- + +- user application +- component features & platform + +Log Sinks +--------- +- log sinks shall be transparent to the application (e.g. by a facade ) +- console +- File system + + - local + - external mounted PCIe Drive + - Cloud native drive via network + +- Network (incl. second dedicated Ethernet Channel) +- Logs shall appear on stdout when running unit tests + +Configuration +------------- + +- Log level +- Log Sinks + + - Log storage device + - Log storage strategy (e.g., on system shutdown, on each message, on demand, on file size, on cache size, with circular or linear buffer) + +- Buffer size +- Storage size (e.g. storage size of log files) +- Permission settings +- log filter +- Logging entity ID (e.g., ECU ID, Application ID, Context ID such as in DLT) +- On-demand functionality (e.g., enable / disable the log storage) +- Provide fallback configs. E.g.: App, System-wide + +- Possibility to provide an extension for custom types + +Error handling +-------------- + +- reboot/reset +- On logging errors, the framework should continue if recoverable; otherwise, deactivate silently and set an error state reported on shutdown. +- The user application should not be affected by logging framework errors. + +Context +------- + +- Supported operating system: QNX, Linux (encapsulation via OSAL) +- Supported programming languages: C++, Rust, Python (e.g. for tests) + +Resource consumption +-------------------- + +- Storage +- Communication Channel +- Runtime resources +- Low impact on overall performance ---> QoS for handling overflows/dropping log messages + +Norms/Standards +--------------- +The logging framework should be compatible with the Diagnostic Log and Trace (DLT) protocol. This includes: + +- Support for DLT message format +- Ability to send and receive DLT messages +- Integration with existing DLT tools and infrastructure + +Backwards Compatibility +======================= +\- + +Security Impact +=============== + +- only authorized users should be able to access the log files + +Safety Impact +============= + +- The interface should support the ASIL level of the user function. +- Dependent on the Safety concept of the over all system, the logging should be classified accordingly. + That could be the case if the logging information are part of the verification strategy.. + +License Impact +============== + +- not known + +How to Teach This +================= + +How to Use: Logging Guideline + + +Definitions +=========== + +Logging +------- + +Write out some message +General progress description (incl. Context) +- state changes +- Infos +- errors + +When logging from a library, it shall be possible to easily associate the logs to the library. A solution could be to provide contexts. + +Tracing +------- + +Example - User need to correlate kernel traces to user traces for debugging , analyzing etc +Follow the control flow (on function call basis)of the application. + +Recompute +--------- + +All data to recompute a module (Input, Output, States) diff --git a/docs/features/analysis-infra/logging/mw-fr_logging_DD_Input.rst_tmp b/docs/features/analysis-infra/logging/mw-fr_logging_DD_Input.rst_tmp new file mode 100644 index 0000000000..2576579d70 --- /dev/null +++ b/docs/features/analysis-infra/logging/mw-fr_logging_DD_Input.rst_tmp @@ -0,0 +1,44 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +This document includes the detailed design findings from the feature request review. + +Logging +####### + +Specification +============= +Context +------- +.. related feature from feature request +- Supported programming languages: C++, Rust, Python (e.g. for tests) + +.. detailed design finding +For Rust, we would like to be able to use the log crate. It provides an (allocation-free) facade without forcing a specific logger implementation. Advantages of using this facade: + +We stay with language best-practices. +New contributors directly feel at home with the logging. +Any library dependency which we might use probably logs against this facade. So we would get logs of dependencies for free by using it as well and implementing a logger for the facade. +There might be comparable defacto standards for C++ and Python. + + +Resource consumption +-------------------- +.. related feature from feature request +- Runtime ressources +- Low impact on overall performance ---> QoS for handling overflows/dropping log messages + +.. detailed design finding +Ideally, in a language like Rust, logging messages should be possible without allocations for individual logs. +Using the defacto standard log crate as facade, implementors of this facade should not allocate to write / forward log messages. diff --git a/docs/features/analysis-infra/logging/mw-log-api/index.rst b/docs/features/analysis-infra/logging/mw-log-api/index.rst deleted file mode 100644 index 04e6ec3a6a..0000000000 --- a/docs/features/analysis-infra/logging/mw-log-api/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Logging API -########### diff --git a/docs/features/analysis-infra/logging/tests/integration-tests/.gitkeep b/docs/features/analysis-infra/logging/tests/integration-tests/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/features/analysis-infra/logging/console-output/index.rst b/docs/features/analysis-infra/tracing/index.rst similarity index 92% rename from docs/features/analysis-infra/logging/console-output/index.rst rename to docs/features/analysis-infra/tracing/index.rst index 1ef9f5e1af..b8b98ee6ee 100644 --- a/docs/features/analysis-infra/logging/console-output/index.rst +++ b/docs/features/analysis-infra/tracing/index.rst @@ -12,5 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Console Output -############## +Tracing +####### + +.. toctree:: + :maxdepth: 1 diff --git a/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp b/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp new file mode 100644 index 0000000000..766de45cf8 --- /dev/null +++ b/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp @@ -0,0 +1,118 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Request +############### + +.. document:: doc__tracing + :id: doc__tracing + :status: draft + :safety: ASIL_D + :tags: contribution_request, feature_request + +.. attention:: + The above directive must be updated according to your Feature. + + - Modify ``name`` to be your Feature Name + - Modify ``id`` to be your Feature Name in upper snake case preceded by ``DOC_`` + - Adjust ``status`` to be ``valid`` + - Adjust ``asil`` according to your needs + - Extend ``tags`` according to your needs, but please keep two default tags there + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_Tracing`` + + .. note:: + The feature flag must reflect the feature name in snake_case. Further, it is prepended with ``experimental_``, as + long as the feature is not yet stable. + + +Abstract +======== + +[A short (~200 word) description of the contribution being addressed.] + + +Motivation +========== + +[Clearly explain why the existing platform/project solution is inadequate to address the topic that the Feature Request solves.] + + .. note:: + The motivation is critical for Feature Requests that want to change the existing features or infrastructure. + It should clearly explain why the existing solution is inadequate to address the topic that the Feature Request solves. + Feature Request submissions without sufficient motivation may be rejected. + + +Rationale +========= + +[Describe why particular design decisions were made.] + + + .. note:: + The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. + + +Specification +============= + +[Describe the requirements, architecture of any new feature.] or +[Describe the change to requirements, architecture, implementation, process, documentation, infrastructure of any change request.] + +Backwards Compatibility +======================= + +[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] + + +Security Impact +=============== + +[How could a malicious user take advantage of this new feature?] + + .. note:: + If there are security concerns in relation to the Feature Request, those concerns should be explicitly written out to make sure reviewers of the Feature Request are aware of them. + + + +Safety Impact +============= + +[How could the safety be impacted by the new feature?] + + .. note:: + If there are safety concerns in relation to the Feature Request, those concerns should be explicitly written out to make sure reviewers of the Feature Request are aware of them. + ToDo - Link to the Safety Impact Method + +[What is the expected ASIL level?] +[What is the expected classification of the contribution?] + + .. note:: + Use the component classification method here to classfiy your component, if it shall to be used in a safety context: (TODO: add link to component classification). + + +License Impact +============== + +[How could the copyright impacted by the license of the new contribution?] + + +How to Teach This +================= From eb120a929b42e88a4b23de00560c72aebadeffa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20H=C3=B6nle?= Date: Fri, 6 Jun 2025 16:59:51 +0200 Subject: [PATCH 014/102] com: rework Lola Architecture (#1133) * com: rework Lola Architecture - Split between communication and IPC - include modules - baselibs - lola * lola: fix review findings - find review findings - correct interfaces communication uses baselibs * lola: rework folder architecture --- .../_assets/lola_layers.drawio.svg | 0 .../communication/docs/architecture/index.rst | 144 +++++++ .../{ipc => docs}/requirements/index.rst | 234 +++++------ docs/features/communication/index.rst | 308 ++++++++++++++- .../ipc/architecture/_assets/stat_arch.puml | 98 ----- .../architecture/component_architecture.rst | 368 ------------------ .../ipc/architecture/feature_architecture.rst | 58 --- .../architecture/_assets/dyn_arch.puml | 0 .../_assets/lola_message_passing.drawio.svg | 0 .../_assets/lola_mixed_crit_1_n.drawio.svg | 0 .../_assets/lola_slots.drawio.svg | 0 .../ipc/docs/architecture/index.rst | 224 +++++++++++ .../ipc/docs/requirements/index.rst | 59 +++ .../communication/ipc/{ => docs}/roadmap.rst | 2 +- .../ipc/{ => docs}/safety_planning/index.rst | 6 +- docs/features/communication/ipc/index.rst | 366 ++--------------- .../communication/modules/baselibs/index.rst | 36 ++ .../baselibs/json_component_architecture.rst | 48 +++ .../memory_shared_component_architecture.rst | 64 +++ ...message_passing_component_architecture.rst | 44 +++ .../configuration_component_architecture.rst | 29 ++ .../frontent_component_architecture.rst | 86 ++++ .../modules/communication/index.rst | 41 ++ .../ipc_binding_architecture.rst | 29 ++ .../mock_binding_architecture.rst | 29 ++ docs/features/communication/modules/index.rst | 22 ++ .../communication/modules/logging/index.rst | 61 +++ .../architecture => modules/os}/index.rst | 25 +- .../os/libc_component_architecture.rst | 147 +++++++ .../os/message_passing_architecture.rst | 62 +++ .../communication/modules/tracing/index.rst | 49 +++ .../safety_management.rst | 2 +- 32 files changed, 1646 insertions(+), 995 deletions(-) rename docs/features/communication/{ipc/architecture => }/_assets/lola_layers.drawio.svg (100%) create mode 100644 docs/features/communication/docs/architecture/index.rst rename docs/features/communication/{ipc => docs}/requirements/index.rst (66%) delete mode 100644 docs/features/communication/ipc/architecture/_assets/stat_arch.puml delete mode 100644 docs/features/communication/ipc/architecture/component_architecture.rst delete mode 100644 docs/features/communication/ipc/architecture/feature_architecture.rst rename docs/features/communication/ipc/{ => docs}/architecture/_assets/dyn_arch.puml (100%) rename docs/features/communication/ipc/{ => docs}/architecture/_assets/lola_message_passing.drawio.svg (100%) rename docs/features/communication/ipc/{ => docs}/architecture/_assets/lola_mixed_crit_1_n.drawio.svg (100%) rename docs/features/communication/ipc/{ => docs}/architecture/_assets/lola_slots.drawio.svg (100%) create mode 100644 docs/features/communication/ipc/docs/architecture/index.rst create mode 100644 docs/features/communication/ipc/docs/requirements/index.rst rename docs/features/communication/ipc/{ => docs}/roadmap.rst (98%) rename docs/features/communication/ipc/{ => docs}/safety_planning/index.rst (96%) create mode 100644 docs/features/communication/modules/baselibs/index.rst create mode 100644 docs/features/communication/modules/baselibs/json_component_architecture.rst create mode 100644 docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst create mode 100644 docs/features/communication/modules/baselibs/message_passing_component_architecture.rst create mode 100644 docs/features/communication/modules/communication/configuration_component_architecture.rst create mode 100644 docs/features/communication/modules/communication/frontent_component_architecture.rst create mode 100644 docs/features/communication/modules/communication/index.rst create mode 100644 docs/features/communication/modules/communication/ipc_binding_architecture.rst create mode 100644 docs/features/communication/modules/communication/mock_binding_architecture.rst create mode 100644 docs/features/communication/modules/index.rst create mode 100644 docs/features/communication/modules/logging/index.rst rename docs/features/communication/{ipc/architecture => modules/os}/index.rst (59%) create mode 100644 docs/features/communication/modules/os/libc_component_architecture.rst create mode 100644 docs/features/communication/modules/os/message_passing_architecture.rst create mode 100644 docs/features/communication/modules/tracing/index.rst diff --git a/docs/features/communication/ipc/architecture/_assets/lola_layers.drawio.svg b/docs/features/communication/_assets/lola_layers.drawio.svg similarity index 100% rename from docs/features/communication/ipc/architecture/_assets/lola_layers.drawio.svg rename to docs/features/communication/_assets/lola_layers.drawio.svg diff --git a/docs/features/communication/docs/architecture/index.rst b/docs/features/communication/docs/architecture/index.rst new file mode 100644 index 0000000000..334788a26f --- /dev/null +++ b/docs/features/communication/docs/architecture/index.rst @@ -0,0 +1,144 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _com_architecture: + +Architecture +============ + +Overview +-------- + +An brief overview of communication is described :ref:`here `. + +Description +----------- + +A description of the communication module is located :ref:`here ` + +.. _com_static_architecture: + +Static Architecture +------------------- + +As discussed in :ref:`com_rationale`, the overall architecture of the communication framework must be layered. This is required, to separate the frontend from the underlying communication mechanisms (also called bindings). + +This ensures a stable public API, independent of the underlying binding(s). At the same time, the communication framework can support many different communication protocols in a flexible manner. + +.. feat_arc_sta:: Feature Architecture Communication + :id: feat_arc_sta__com__communication + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__com__interfaces + :includes: logic_arc_int__communication__user + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_feature(need(), needs) }} + mod_view_sta__tracing__tracing -[hidden]-> mod_view_sta__baselibs__baselibs + +In the following sections we will look on the different architectural elements of the communication framework in more +detail. + +Frontend +^^^^^^^^ + +The frontend is responsible of providing a stable public API to the user. In general, the communication framework (`mw::com`) follows the client-server, pub-sub and producer-consumer patterns. + +Following these patterns, the user interacts with different APIs depending on whether he is producer/server or +consumer/client. + +A producer creates a `Skeleton` to communicate with consumers. Each consumer creates a `Proxy` to connect to a producer. Consumers can find available producers through a service discovery mechanism. This mechanism is tightly bound to the `Proxy`, to only discover producers offering a compatible implementation of a `Skeleton`. + +.. uml:: + :scale: 50 + :align: center + :name: doc__communication__proxy_skeleton + :caption: Communication through mw::com + + package "Consumer" <> { + package "Frontend" <> #D5E8D4 { + object "Proxy" as proxy_t + } + package "Binding" <> #DAE8FC { + object "Proxy" as proxy_b + } + } + + package "Producer" <> { + package "Frontend" <> #D5E8D4 { + object "Skeleton" as skeleton_t + } + package "Binding" <> #DAE8FC { + object "Skeleton" as skeleton_b + } + } + + skeleton_t -d-> skeleton_b + proxy_t -d-> proxy_b + proxy_b -l(0- skeleton_b + +In addition to these elements, a runtime singleton is used for background tasks to reduce resource consumption. This runtime is invisible to the user. This runtime is responsible for service discovery (explained in :ref:`ipc_service_discovery`), notification reception and other infrastructure tasks. + +Compatibility of *Skeleton* and *Proxy* is currently defined by them sharing the same communication interface. Additionally, versioning will be taken into account in the future (see :ref:`ipc_roadmap`). + +The communication interface for now consists of events. Support for methods and signals will be added in the future +(see :ref:`ipc_roadmap`). + +Since S-CORE supports strongly typed programming languages, the API of *Skeleton* and *Proxy* is also strongly typed. Instead of a code generator, we utilize features like templates in C++ and macros in Rust to "generate" the necessary code at compile time. + +But there are some "niche" use cases, where the need to "regenerate" and recompile the *Proxy* can be detrimental. +This is the case when: + +- signatures are trivial and changes/differences between them are minimal +- the communicated data/payload gets handled very generically (loosely typed) anyhow +- the communicated data/payload has to get deep-inspected based on additional/separate type-information anyhow + +For these cases *mw::com* provides a *GenericProxy* that allows introspection of communication interfaces at runtime. + +While the frontend is based on a communication model, it is independent from any communication protocol. Therefore, it always forwards user requests to the binding(s) underneath. Which bindings to use is defined in a configuration file. + +A multi-binding approach is chosen, where API calls are mapped to a set of selected bindings. + +Interface Description +^^^^^^^^^^^^^^^^^^^^^ + +The public API for the frontend is defined as: + +.. logic_arc_int:: Communication User Interface + :id: logic_arc_int__communication__user + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__com__interfaces + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +Bindings +^^^^^^^^ + +The need for bindings was discussed in :ref:`com_multi_binding_support`. +Bindings reside beneath the frontend layer and accept the forwarded requests + +Currently, the available bindings are: + +- :ref:`IPC (LoLa) ` +- :ref:`mock binding ` diff --git a/docs/features/communication/ipc/requirements/index.rst b/docs/features/communication/docs/requirements/index.rst similarity index 66% rename from docs/features/communication/ipc/requirements/index.rst rename to docs/features/communication/docs/requirements/index.rst index a75ee638bc..bd54688a6e 100644 --- a/docs/features/communication/ipc/requirements/index.rst +++ b/docs/features/communication/docs/requirements/index.rst @@ -1,6 +1,6 @@ .. # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation + # Copyright (c) 2025 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,48 +12,47 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Requirements -############ +.. _com_requirements: -High cohesion and loose coupling -================================ +Requirements +============ .. feat_req:: Support for Time-based Architecture - :id: feat_req__ipc__time_based_arch + :id: feat_req__com__time_based_arch :reqtype: Functional :security: NO - :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_time + :safety: ASIL_B + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time :status: valid The communication framework shall provide API to support a time-based architecture. .. feat_req:: Support for Data-driven Architecture - :id: feat_req__ipc__data_driven_arch + :id: feat_req__com__data_driven_arch :reqtype: Functional :security: NO :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data :status: valid The communication framework shall provide API to support a data-driven architecture. .. feat_req:: Support for Request-driven Architecture - :id: feat_req__ipc__request_driven_arch + :id: feat_req__com__request_driven_arch :reqtype: Functional :security: NO :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_request :status: valid The communication framework shall provide API to support a request-driven architecture. .. feat_req:: Communication Interfaces - :id: feat_req__ipc__interfaces + :id: feat_req__com__interfaces :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data,stkh_req__app_architectures__support_request + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data,stkh_req__app_architectures__support_request :status: valid A communication interface consists of a combination of any number of the following elements: @@ -63,11 +62,11 @@ High cohesion and loose coupling - Signals .. feat_req:: Event Type - :id: feat_req__ipc__event_type + :id: feat_req__com__event_type :reqtype: Functional :security: NO - :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data + :safety: ASIL_B + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data :status: valid An event-type is part of a communication interface and has: @@ -79,11 +78,11 @@ High cohesion and loose coupling Consumers can subscribe to value-changed events of the element or poll unseen, cached events. .. feat_req:: Method - :id: feat_req__ipc__method + :id: feat_req__com__method :reqtype: Functional :security: NO - :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_request + :safety: ASIL_B + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_request :status: valid A method is part of a communication interface and has: @@ -93,17 +92,17 @@ High cohesion and loose coupling When a communication partner issues a call to the method with the required parameters: - 1. it shall invoke the application routine with the provided parameters, and - 2. return its result to the communication partner + #. it shall invoke the application routine with the provided parameters, and + #. return its result to the communication partner A method call shall be possible both synchronously and asynchronously. .. feat_req:: Signal - :id: feat_req__ipc__signal + :id: feat_req__com__signal :reqtype: Functional :security: NO :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_time + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time :status: valid A signal is part of a communication interface and has: @@ -116,34 +115,35 @@ High cohesion and loose coupling - wait for the signal to be triggered - check if the signal was triggered - Note: Signals can not transport data. They are meant to be fast synchronization mechanism with low setup cost. - Thus, depending on the location of the communication partners primitives like Linux Signals or QNX Pulses or - Hypervisor Signalling APIs may be chosen. + .. note:: + Signals can not transport data. They are meant to be fast synchronization mechanism with low setup cost. Thus, depending on the location of the communication partners primitives like Linux Signals or QNX Pulses or Hypervisor Signalling APIs may be chosen. + .. feat_req:: Producer-Consumer Pattern - :id: feat_req__ipc__producer_consumer + :id: feat_req__com__producer_consumer :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_time + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time :status: valid Communication shall be cached based on the producer-consumer pattern. .. feat_req:: Service Instance - :id: feat_req__ipc__service_instance + :id: feat_req__com__service_instance :reqtype: Functional :security: NO :safety: ASIL_B :satisfies: stkh_req__communication__inter_process :status: valid - A communication interface that is offered to consumers is called a service instance. - Multiple service instances shall be able to offer the same interface. + .. note:: + A communication interface that is offered to consumers is called a service instance. + .. feat_req:: Service Instance Names - :id: feat_req__ipc__service_instance_names + :id: feat_req__com__service_instance_names :reqtype: Functional :security: NO :safety: ASIL_B @@ -153,27 +153,28 @@ High cohesion and loose coupling A service instance is offered under one or more unique names by which it can be discovered. Names follow a POSIX path style. - Note: The resolution from a service instance name to the protocol-specific identifier is handled by the service - discovery. - + .. note:: + The resolution from a service instance name to the protocol-specific identifier is handled by the service + discovery. .. feat_req:: Versioning - :id: feat_req__ipc__versioning + :id: feat_req__com__versioning :reqtype: Functional :security: NO :safety: ASIL_B :satisfies: stkh_req__communication__inter_process :status: valid - The communication framework shall support versioning of service instances. - Version information of a service instance is binding-specific. - Version information is provided in the deployment configuration. + The communication framework shall support versioning of service instances: - Note: - Multiple service instances can have the same interface and version. + - Version information of a service instance is binding-specific. + - Version information is provided in the deployment configuration. + + .. note:: + Multiple service instances can have the same interface and version. .. feat_req:: Service location transparency - :id: feat_req__ipc__service_location_transparency + :id: feat_req__com__service_location_transparency :reqtype: Functional :security: NO :safety: ASIL_B @@ -181,10 +182,12 @@ High cohesion and loose coupling :status: valid The interface to access service instances is agnostic to the binding used to communicate with the service. - Note: Deployment information may require manual changes based on where the service is located. + + .. note:: + Deployment information may require manual changes based on where the service is located. .. feat_req:: Stateless communication - :id: feat_req__ipc__stateless_communication + :id: feat_req__com__stateless_communication :reqtype: Functional :security: NO :safety: ASIL_B @@ -192,12 +195,13 @@ High cohesion and loose coupling :status: valid The communication framework shall support stateless communication. - Note: - - In case of events, the producer is not aware of its consumers. - - In case of RPC, the skeleton is not aware of the proxy, this request originated from. + + .. note:: + - In case of events, the producer is not aware of its consumers. + - In case of RPC, the skeleton is not aware of the proxy, this request originated from. .. feat_req:: Service instance_granularity - :id: feat_req__ipc__service_instance_granularity + :id: feat_req__com__service_instance_granularity :reqtype: Functional :security: NO :safety: ASIL_B @@ -205,26 +209,29 @@ High cohesion and loose coupling :status: valid The communication framework shall support multiple service instances per software architecture element. - Note: A software architecture element is for example an application, activity, proces, ... + + .. note:: + A software architecture element is for example an application, activity, proces, ... .. feat_req:: Service discovery - :id: feat_req__ipc__service_discovery + :id: feat_req__com__service_discovery :reqtype: Functional :security: NO :safety: ASIL_B :satisfies: stkh_req__communication__inter_process :status: valid - The communication framework shall provide service discovery to find available services during runtime. - Service discovery shall consider version compatibility. - Service discovery shall be handled implicitly (where possible). - Note: The service discovery may be restricted/impacted by availability of deployment information. + The communication framework shall provide service discovery to find available services during runtime. Service discovery shall consider version compatibility. Service discovery shall be handled implicitly (where possible). + + .. note:: + The service discovery may be restricted/impacted by availability of deployment information. + Mixed-Criticality safety systems -================================ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. feat_req:: Safe communication over criticality levels - :id: feat_req__ipc__safe_communication + :id: feat_req__com__safe_communication :reqtype: Functional :security: YES :safety: ASIL_B @@ -235,7 +242,7 @@ Mixed-Criticality safety systems criticality levels. .. feat_req:: Data Corruption - :id: feat_req__ipc__data_corruption + :id: feat_req__com__data_corruption :reqtype: Functional :security: YES :safety: ASIL_B @@ -245,7 +252,7 @@ Mixed-Criticality safety systems Consumers with lower criticality shall not be able to corrupt data consumed by partners with higher criticality. .. feat_req:: Data Reordering - :id: feat_req__ipc__data_reordering + :id: feat_req__com__data_reordering :reqtype: Functional :security: YES :safety: ASIL_B @@ -256,7 +263,7 @@ Mixed-Criticality safety systems criticality. .. feat_req:: Data Repetition - :id: feat_req__ipc__data_repetition + :id: feat_req__com__data_repetition :reqtype: Functional :security: YES :safety: ASIL_B @@ -267,7 +274,7 @@ Mixed-Criticality safety systems higher criticality. .. feat_req:: Data Loss - :id: feat_req__ipc__data_loss + :id: feat_req__com__data_loss :reqtype: Functional :security: YES :safety: ASIL_B @@ -277,24 +284,28 @@ Mixed-Criticality safety systems Consumers with lower criticality shall not be able to drop data before it is consumed by partners with higher criticality. + Performance -=========== +^^^^^^^^^^^ -.. feat_req:: Zero-Copy IPC - :id: feat_req__ipc__zero_copy +.. feat_req:: Zero-Copy Approach + :id: feat_req__com__zero_copy :reqtype: Functional :security: NO :safety: QM :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data :status: valid - IPC communication shall be possible without copying to-be-transferred data. + The communication framework shall enable Zero-Copy communication without copying to-be-transferred data. + + .. note:: + It has to be evaluated on binding level if a Zero-Copy approach is applicable for the respective binding. User friendly API for information exchange -========================================== +------------------------------------------ .. feat_req:: Support for multiple programming languages - :id: feat_req__ipc__multi_lang + :id: feat_req__com__multi_lang :reqtype: Non-Functional :security: NO :safety: QM @@ -304,7 +315,7 @@ User friendly API for information exchange The communication framework shall provide a public API for each supported programming language of S-CORE. .. feat_req:: Support for programming language idioms - :id: feat_req__ipc__lang_idioms + :id: feat_req__com__lang_idioms :reqtype: Non-Functional :security: NO :safety: QM @@ -314,7 +325,7 @@ User friendly API for information exchange Each public API shall support the idioms of the programming language it is written in. .. feat_req:: Use programming language infrastructure - :id: feat_req__ipc__lang_infra + :id: feat_req__com__lang_infra :reqtype: Non-Functional :security: NO :safety: QM @@ -324,13 +335,14 @@ User friendly API for information exchange Each public API shall use core infrastructure of its programming language and accompanying standard libraries, whenever possible and meaningful. - Note: This includes error handling. + .. note:: + This includes error handling. Full testability for the user facing API -======================================== +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. feat_req:: Fully mockable public API - :id: feat_req__ipc__testability_mock_api + :id: feat_req__com__testability_mock_api :reqtype: Non-Functional :security: NO :safety: QM @@ -340,7 +352,7 @@ Full testability for the user facing API The public API shall be fully mockable. .. feat_req:: Fake binding - :id: feat_req__ipc__testability_fake_binding + :id: feat_req__com__testability_fake_binding :reqtype: Non-Functional :security: NO :safety: QM @@ -349,11 +361,12 @@ Full testability for the user facing API The communication framework shall provide a fake binding. + Multi-binding support -===================== +^^^^^^^^^^^^^^^^^^^^^ .. feat_req:: Multi-binding support - :id: feat_req__ipc__multi_binding_support + :id: feat_req__com__multi_binding_support :reqtype: Functional :security: NO :safety: QM @@ -362,12 +375,11 @@ Multi-binding support The communication framework shall support multiple bindings. - Note: - A binding performs the conversion of user communication to the respective communication protocol. - It does this either directly or via a gateway approach. + .. note:: + A binding performs the conversion of user communication to the respective communication protocol. It does this either directly or via a gateway approach. .. feat_req:: Binding-agnostic public API - :id: feat_req__ipc__binding_agnostic_api + :id: feat_req__com__binding_agnostic_api :reqtype: Functional :security: NO :safety: QM @@ -376,25 +388,24 @@ Multi-binding support The public API of the communication framework shall be binding-agnostic. - Note: - Binding-agnostic in this context means, that the public API is independent of the binding underneath. E.g., if the - binding is exchanged, the public API remains syntactically and semantically unchanged. + .. note:: + Binding-agnostic in this context means, that the public API is independent of the binding underneath. E.g., if the binding is exchanged, the public API remains syntactically and semantically unchanged. .. feat_req:: Multi-binding deployment configuration - :id: feat_req__ipc__multi_binding_depl + :id: feat_req__com__multi_binding_depl :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__communication__inter_process :status: valid The association of a service instance and the appropriate binding shall be specified in the deployment configuration. Dynamic deployment at runtime -============================= +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. feat_req:: Deployment configuration at runtime - :id: feat_req__ipc__depl_config_runtime + :id: feat_req__com__depl_config_runtime :reqtype: Functional :security: YES :safety: ASIL_B @@ -404,10 +415,10 @@ Dynamic deployment at runtime Deployment configuration shall be read from an integrity-checked configuration file at runtime. Tracing -======= +------- .. feat_req:: Support for Tracing - :id: feat_req__ipc__tracing + :id: feat_req__com__tracing :reqtype: Functional :security: NO :safety: ASIL_B @@ -418,10 +429,10 @@ Tracing communication. Security Impact -=============== +--------------- .. feat_req:: Access Control List Placement - :id: feat_req__ipc__acl_placement + :id: feat_req__com__acl_placement :reqtype: Functional :security: YES :safety: QM @@ -431,7 +442,7 @@ Security Impact The communication framework shall support an Access Control Lists in the deployment configuration. .. feat_req:: Access Control List per service instance - :id: feat_req__ipc__acl_per_service_instance + :id: feat_req__com__acl_per_service_instance :reqtype: Functional :security: YES :safety: QM @@ -441,7 +452,7 @@ Security Impact The communication framework shall support an Access Control List per service instance. .. feat_req:: Access Control List for producer - :id: feat_req__ipc__acl_for_producer + :id: feat_req__com__acl_for_producer :reqtype: Functional :security: YES :safety: QM @@ -453,7 +464,7 @@ Security Impact An entry in the ACL corresponds to an allowed consumer. .. feat_req:: Access Control List for consumer - :id: feat_req__ipc__acl_for_consumer + :id: feat_req__com__acl_for_consumer :reqtype: Functional :security: YES :safety: QM @@ -464,42 +475,11 @@ Security Impact instance. An entry in the ACL corresponds to an allowed producer. -.. feat_req:: IPC Confidentiality - :id: feat_req__ipc__confidentiality - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__communication__inter_process - :status: valid - - The IPC binding shall ensure confidentiality of its communication. - -.. feat_req:: IPC Integrity - :id: feat_req__ipc__integrity - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__communication__inter_process - :status: valid - - The IPC binding shall ensure integrity of its communication. - -.. feat_req:: IPC Availability - :id: feat_req__ipc__availability - :reqtype: Functional - :security: YES - :safety: QM - :satisfies: stkh_req__communication__inter_process - :status: valid - - The IPC binding shall ensure availability of its communication, so that the availability is independent per - criticality level. - Safety Impact -============= +------------- -.. feat_req:: IPC ASIL level - :id: feat_req__ipc__asil +.. feat_req:: Communication ASIL level + :id: feat_req__com__asil :reqtype: Functional :security: YES :safety: ASIL_B diff --git a/docs/features/communication/index.rst b/docs/features/communication/index.rst index b6f9527966..712437b522 100644 --- a/docs/features/communication/index.rst +++ b/docs/features/communication/index.rst @@ -12,12 +12,318 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +.. _com_feature: + Communication ############# +.. document:: Communication + :id: doc__com + :status: valid + :tags: feature_request + .. toctree:: :maxdepth: 1 :glob: :titlesonly: + :hidden: + + docs/**/index + ipc/index + modules/index + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_com`` + +.. _com_abstract: + +Abstract +======== + +The Communication Module contains: + +- an abstraction layer to enable different communication mechanisms (aka Frontend) +- different bindings which provide the communication functionality (e.g. IPC or Some/IP) + +The abstraction layer is designed in a way to ensure full testability for an end-user, while enabling runtime selection +of the underlying communication mechanism with the help of different bindings (e.g. IPC, Some/IP ...). + +It provides the user with a high-level API to focus on the content of information – and not on low-level specifics of the used binding. The concept is displayed in Figure :numref:`lola_layers` + +.. figure:: _assets/lola_layers.drawio.svg + :align: center + :name: lola_layers + + Layered architecture with binding-agnostic mw::com and bindings beneath + +.. _com_rationale: + +Rationale +========= + +S-CORE is targeting high-performance automotive systems with safety impact. In general, these systems consist of multiple processes that are executed on an operating system which also exchange information with other CPUs or ECUs in the system. + +Key aspects of S-CORE and therefore also the Communication framework are: + +#. :ref:`High cohesion and loose coupling ` +#. :ref:`Mixed-criticality safety systems ` +#. :ref:`Performance ` +#. :ref:`API Management ` + +But also secondary aspect for the Communication framework should not be neglected: + +#. :ref:`User friendly API for information exchange ` +#. :ref:`Full testability for the user facing API ` +#. :ref:`Multi-Binding Support ` +#. :ref:`Tracing ` + +To provide a clearer picture we define which basic communication patterns the framework shall support. S-CORE defines in its stakeholder requirements different architectures that must be supported by the communication framework. This leads to the three requirements: + +- :need:`Time Based Architecture ` +- :need:`Data Driven Architecture ` +- :need:`Request Driven Architecture ` + +Based on this, the basic communication elements consist of: + +- :need:`Events ` +- :need:`Methods ` +- :need:`Signals ` + +Since often communication regarding a specific feature consists of many of these elements, we allow grouping of them +through :need:`communication interfaces `. + +To allow more flexible scheduling of the system and as a prerequisite of :need:`Time based Architecture `, the communication framework must support :need:`caching ` + +Further, we promote :need:`stateless communication` to simplify the communication logic both in the framework as well as the user code. + +We coin the term :need:`Service instance ` to refer to an entity that offers functionality through a communication interface. + +In general, we put no restrains in how :need:`service instances are grouped in the architecture`. +In the following we will explain and argue each one of these different aspects from a top level communication point of view. + +.. _com_specification: + +Specification +============= + +.. _com_high_cohesion_loose_coupling: + +High cohesion and loose coupling +-------------------------------- + +Complex systems require high cohesion and loose coupling to remain maintainable. The benefit of loose coupling is to limit the effect of changes throughout the system. Key to achieve this is stability of interfaces. + +Since the communication of a module is also part of its interface, we must consider its stability. How stable an interface is, largely depends on the implementation reachable through it. This means, the communication framework can not provide stability on its own. It can only provide the necessary tools for developers to consider the stability when changing the interface or implementation. + +.. _com_mixed_criticality: + +Mixed-Criticality safety systems +-------------------------------- + +In complex safety-critical systems, applications often have different criticality. However communication is also required between applications on different criticality levels. + +For example, a service with low-criticality may provide data to a highly critical application. Or the reverse could be the case, where a less critical application depends on data produced by a highly critical one. More complex scenarios are also possible, where the same data is consumed by multiple recipients with different criticality. + +Hence, it is crucial that applications can also safely communicate between different criticality levels. This assumption adds four additional requirements which are based on the failure modes for communication in the ISO26262: + +#. :need:`Data Corruption ` +#. :need:`Data Reordering ` +#. :need:`Data Repetition ` +#. :need:`Data Loss ` + +The communication framework does not take timing related failure modes into account, since the overall stack must +consider such failure modes on a more generic level. + +Support for mixed criticality is a core feature of a communication framework. Hence, it greatly impacts architectural +decisions and influences many other aspects. One of them being performance, which is the third primary aspect of a +communication framework. + +.. _com_performance: + +Performance +----------- + +In the recent years high-performance automotive systems rely more and more on communication of huge amounts of data. This communication must be performant, to enable decomposition of the system. With ever increasing complexity of the tasks automotive systems must tackle, this trend will continue in the future. Hence, architectural decisions for the communication framework must ensure scalable performance. + +In general, good scalable performance can be decomposed into two aspects: + +1. High throughput +2. Low latency + +Further, reliable low-latency communication is only possible with appropriate scheduling. Meaning, if a consumer is not scheduled when he receives an event, the latency of the communication is out of the hand of the communication framework. Thus, the communication framework must be capable to interact with the scheduler to influence the scheduling behavior. + +To also achieve a high throughput the focus of the development shall focus on :need:`zero-copy ` solutions. + +.. _com_api_management: + +API Management +-------------- + +Version compatibility can be separated into *syntactic* compatibility and *semantic* compatibility. Communication partners are only capable to communicate properly with each other, if they are compatible in both domains. Thus, a versioning concept must consider both syntax and semantics. Therefore, it does not suffice to only version communication interfaces. Similarly, only versioning the behavior of the functionality behind an interface is not enough. + +Instead, we define a single version scheme over both syntax and semantics of a service instance. Meaning, whenever the service instance has a syntactic or semantic change, the version must be bumped. This leads to the conclusion that the version is associated to the service instance. + +It is impossible to define a global versioning scheme over all protocols, with their significantly differing +capabilities in that regard. Thus, :need:`version compatibility ` ranges must be supplied per protocol. + +Additional to versioning, loose coupling also requires that the communication partners are unaware of where their +:need:`counterpart resides `. This implies, that communication partners are :need:`discovered dynamically ` at runtime . + +Discovery of communication partners must consider their compatibility based on the versioning concept. + +To retain loose coupling, the public API of the communication framework shall treat discovery implicitly without +unneeded user involvement (:need:`feat_req__com__service_discovery`). Further, service discovery is based on a naming scheme where each service instance is associated to one or more names (:need:`feat_req__com__service_instance_names`). + +.. _com_user_friendly_api: + +User friendly API for information exchange +------------------------------------------ + +Programming languages have their own feature set and idioms. It is crucial for any library that it seamlessly integrates into both. This means, wherever possible and meaningful, infrastructure of the programming language and accompanying standard libraries shall be reused. Further, a developer used to the programming language shall have no problems understanding the API. It should feel natural to use. This includes error handling, which shall follow one of the error handling concepts of the programming language. + +#. :need:`Language Idioms ` +#. :need:`Language infrastructure ` + +Since S-CORE supports multiple :need:`programming languages `, this leads to multiple APIs that might diverge significantly from each other, but provide the same feature set to the user. +To support something like this, without reimplementing the full communication stack in both languages, an abstraction +layer within the communication framework is unavoidable. + +:need:`feat_req__com__multi_lang` + +.. _com_testability_user_facing_api: + +Full testability for the user facing API +---------------------------------------- + +Our users will be required to proof certain coverage metrics, like line coverage or MC/DC coverage. For them to reach full coverage, they need to be easily able to mock or fake parts of the communication systems in their unit tests. + +Most of the current solutions (e.g. ara::com) keep this outside their requirements. This forces the users to introduce an additional abstraction layer over the communication framework to inject test doubles. + +This is additional work for the user, and abstraction layers come with a certain cost in runtime and maintenance. Our goal is to provide an API that requires no additional abstraction layer over the communication framework. + +:need:`feat_req__com__testability_mock_api` + +In some test scenarios users must fake communication: + +Instead of mocking the fine-granular behavior of the framework, users shall be able to simulate communication simply by +providing an implementation of the communication partner in the test environment. For communication this does not require big architectural decisions. In the light of a robust API that also supports communication between multiple hosts, this can be achieved through multi-binding support. + +:need:`feat_req__com__testability_fake_binding` + +.. _com_multi_binding_support: + +Multi-binding support +--------------------- + +Following the idea of service location transparency, we introduce multi-binding support. +A binding is responsible of translating requests from the user to the respective protocol used for communication. +It may do so by directly performing the communication into the chosen protocol without intermediate protocols inbetween. +But it can also use a gateway approach where it forwards the communication using a different protocol (e.g. IPC) to a +gateway which then performs the translation between protocols. + +:need:`feat_req__com__multi_binding_support` + +To enable service location transparency, the public API is designed to be binding-agnostic. +If the binding is exchanged, the public API remains syntactically and semantically unchanged. + +:need:`feat_req__com__binding_agnostic_api` + +The framework forwards requests from the public API to the appropriate binding of the service instance. +Bindings are specified in the deployment configuration. + +:need:`feat_req__com__multi_binding_depl` + +Some possible bindings are: + +- :need:`IPC ` +- :need:`SOME/IP ` +- :need:`DDS ` +- :ref:`fake binding` (for testing) + +In the beginning, S-CORE will only provide inter-process communication. +But this will not suffice for later. +A communication framework for high-performance automotive systems with safety impact will require support for +communication to other VMs or hosts. + +.. _mock_binding: + +Mock Binding +^^^^^^^^^^^^ + +To support users in their testing efforts, the communication framework must provide support for mocking and faking. +Since the public API of mw::com is highly templated, most testing frameworks would reach their limits. +So instead of making the public API directly mockable, we use the binding concept to provide a mock binding. +The mock binding utilizes the GMock framework. + +.. _dynamic_deployment_runtime: + +Dynamic deployment at runtime +----------------------------- + +In the context of safety, security and startup requirements, `Service discovery` without some deployment information is +not ideal. +For this reason, most implementations prefer a limited `Service discovery` and supply partial deployment information +in advance. +We too provide partial deployment information through configuration files read at runtime. +This information is enriched through a runtime `Service discovery`. + +:need:`feat_req__com__depl_config_runtime` + +.. _com_tracing: + +Tracing +------- + +The communication framework must support :need:`tracing of communication events `. In a framework with multiple bindings, this requires a zero-copy binding-agnostic tracing solution in the abstraction layer. + +:need:`feat_req__com__tracing` + + +Architecture +------------ + +The architecure of communication is displayed :ref:`here` + +Requirements +------------ + +The requirements for communication are listed :ref:`here` + +.. _com_security_impact: + +Security Impact +=============== + +Security of communication is important for the security of the overall system. +To efficiently handle security with the least amount of overhead, each binding must determine the best security approach +for its circumstances. + +Depending on the binding, the security approach may achieve different +`security goals `_. + +To provide users a generic concept of security configuration on the level of interfaces, the chosen solution of every +binding must map at least to an Access Control List (ACL) concept, but may have additional deployment configuration +options. + +The ACL of each service instance is defined in the deployment configuration of producer and consumer. + +- :need:`ACL Placement ` +- :need:`ACL per Service Instance ` + +Entries in the ACL of: + +- the producer list the :need:`allowed consumers ` +- the consumer list the :need:`allowed producers ` + +.. _com_safety_impact: + +Safety Impact +============= + +The safety impact was already exhaustively covered in :ref:`com_mixed_criticality`. - */index +Overall, the communication framework supports use cases up to :need:`ASIL-B `. Future extension to ASIL-D use cases is feasible but not in scope for now. diff --git a/docs/features/communication/ipc/architecture/_assets/stat_arch.puml b/docs/features/communication/ipc/architecture/_assets/stat_arch.puml deleted file mode 100644 index bb493cf693..0000000000 --- a/docs/features/communication/ipc/architecture/_assets/stat_arch.puml +++ /dev/null @@ -1,98 +0,0 @@ -/' - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* -'/ -allowmixing - -component "User Application" as UA - -package IPC <> as feat_ipc { - - interface "mw::com" as mwcom { - } - - package IPC as mod_ipc <> { - component "mw::com" <> as lola - } - - package os as os <> { - component "OS::RAMFS" as osramfs - component "OS::FS" as osfs - component "OS::IPC" as osipc - component "OS::ACL" as osacl - component "OS::inotify" as osinotify - } - - package logging as logging <> { - component "log::ipctracing" as ipctracing - } - - package json as mod_json <> { - component "json" as json - } - - interface "ipctracing" as i_ipctracing { - } - - interface "communication binding configuration" as i_combind { - file: mw_com_config.json - type: persistent memory, read-only - } - - interface "posix files" as i_pf { - file: /dev/shm - type: shared memory - } - - interface "Access Control List" as i_acl { - file: access control of shared memory objects - type: shared memory - ACL control of file owners / permissions - } - - interface "IPC" as i_ipc { - file: IPC as a control channel for shared memory - type: OS::IPC - } - - interface "flock" as i_flock{ - file: unique ownership of marker files during process lifetime - type: shared memory - } - - interface "inotify" as i_inotify{ - file: event based information of file creation, alteration or deletion - type: inotify, shared memory - } - - mod_ipc -u-|> mwcom : implement - - mod_ipc -d[dashed]-> i_pf : use - mod_ipc -d[dashed]-> i_acl : use - mod_ipc -d[dashed]-> i_ipc : use - mod_ipc -d[dashed]-> i_flock : use - mod_ipc -d[dashed]-> i_inotify : use - mod_ipc -d[dashed]-> i_combind : use - mod_ipc -d[dashed]-> i_ipctracing : use - - json -u-|> i_combind : implement - ipctracing -u-|> i_ipctracing : implement - - osramfs -u-|> i_pf : implement - osacl -u-|> i_acl : implement - osipc -u-|> i_ipc : implement - osfs -u-|> i_flock : implement - osinotify -u-|> i_inotify : implement -} - -UA -d-> mwcom : use diff --git a/docs/features/communication/ipc/architecture/component_architecture.rst b/docs/features/communication/ipc/architecture/component_architecture.rst deleted file mode 100644 index dd66820208..0000000000 --- a/docs/features/communication/ipc/architecture/component_architecture.rst +++ /dev/null @@ -1,368 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Component Architecture -###################### - -Technical Concept Description -***************************** - -As discussed in :ref:`ipc_feature`, the overall architecture of the communication framework must be layered. -This is required, to separate the frontend from the underlying communication mechanisms (also called bindings). - -This ensures a stable public API, independent of the underlying binding(s). -At the same time, the communication framework can support many different communication protocols in a flexible manner. - -.. image:: _assets/lola_layers.drawio.svg - :alt: Layered architecture with binding-agnostic mw::com and bindings beneath - -In the following sections we will look on the different architectural elements of the communication framework in more -detail. - -Frontend -======== - -The frontend is responsible of providing a stable public API to the user. -In general, the communication framework (`mw::com`) follows the client-server, pub-sub and producer-consumer patterns. - -Following these patterns, the user interacts with different APIs depending on whether he is producer/server or -consumer/client. - -A producer creates a `Skeleton` to provide events to consumers. -Each consumer creates a `Proxy` to connect to a producer. -Consumers can find available producers through a service discovery mechanism. -This mechanism is tightly bound to the `Proxy`, to only discover producers offering a compatible implementation of a -`Skeleton`. - -.. document:: Communication through mw::com - :id: doc__communication__proxy_skeleton - :safety: ASIL_B - :status: valid - - .. needarch:: - :scale: 50 - :align: center - - allowmixing - - - package "Consumer" <> { - package "Frontend" <> #D5E8D4 { - object "Proxy" as proxy_t - } - package "Binding" <> #DAE8FC { - object "Proxy" as proxy_b - } - } - - package "Producer" <> { - package "Frontend" <> #D5E8D4 { - object "Skeleton" as skeleton_t - } - package "Binding" <> #DAE8FC { - object "Skeleton" as skeleton_b - } - } - - skeleton_t -d-> skeleton_b - proxy_t -d-> proxy_b - proxy_b -l(0- skeleton_b - -Additional to these elements, a runtime singleton is used for background tasks to reduce resource consumption. -This runtime is invisible to the user. -This runtime is responsible for service discovery (explained in :ref:`service_discovery`), notification reception and -other infrastructure tasks. - -Compatibility of `Skeleton` and `Proxy` is currently defined by them sharing the same communication interface. -Additionally, versioning will be taken into account in the future (see :ref:`roadmap`). - -The communication interface for now consists of events. Support for methods and signals will be added in the future -(see :ref:`roadmap`). - -Since S-CORE supports strongly typed programming languages, the API of `Skeleton` and `Proxy` is also strongly typed. -Instead of a code generator, we utilize features like templates in C++ and macros in Rust to "generate" the necessary -code at compile time. - -But there are some "niche" use cases, where the need to "regenerate" and recompile the `Proxy` can be detrimental. -This is the case when: - -- signatures are trivial and changes/differences between them are minimal -- the communicated data/payload gets handled very generically (loosely typed) anyhow -- the communicated data/payload has to get deep-inspected based on additional/separate type-information anyhow - -For these cases mw::com provides a `GenericProxy` that allows introspection of communication interfaces at runtime. - -While the frontend is based on a communication model, it is independent from any communication protocol. -Therefore, it always forwards user requests to the binding(s) underneath. -Which bindings to use is defined in a configuration file. - -A multi-binding approach is chosen, where API calls are mapped to a set of selected bindings. -Currently, the available bindings are: - -- IPC (LoLa) -- mock binding - -Bindings -======== - -The need for bindings was discussed in :ref:`multi_binding_support`. -Bindings reside beneath the frontend layer and accept the forwarded requests. - -IPC Binding ------------ - -The basic idea of the ipc binding concept is to use two main operating system facilities: - -1. Shared Memory: Shall be used for the heavy lifting of data exchange -2. Message Passing: Shall be used as notification mechanism - -We decided for this side channel since implementing a notification system via shared memory would include the usage of -condition variables. -These condition variables would require a mutex. -This could lead to the situation that a malicious process could lock the mutex forever and thus destroy any event -notification. -In general we can say that any kind of notification shall be exchanged via message passing facilities. -The section :ref:`message_passing_facilities` below will go into more detail. - -The usage of shared memory has some implications. -First, any synchronization regarding thread-safety / process-safety needs to be performed by the user. -Second, the memory that is shared between the processes is directly mapped into their virtual address space. -This implies that it is easy for a misbehaving process to destroy or manipulate any data within this memory segment. -In order to cope with the latter, we split up the shared memory into three segments. - -- First, a segment where only the to-be-exchanged data is provided. - This segment shall be read-only to consumers and writeable by the producer. - This will ensure that nobody besides the producer process can manipulate the provided data. -- The second and third segment shall contain necessary control information for the data segment. - Necessary control information can include atomics that are used to synchronize the access to the data segments. - Since this kind of access requires write access, we split the shared memory segments for control data by ASIL Level. - This way it can be ensured that no low-level ASIL process interferes with higher level ones. - More information on shared memory handling can be found in :ref:`shared_memory_handling`. - -.. image:: _assets/lola_mixed_crit_1_n.drawio.svg - :alt: Mixed criticality setup for zero-copy IPC - -One of the main ideas in this concept is the split of control data from sample (user) data. -In order to ensure a mapping, the shared memory segments are divided into slots. -By convention, we then define that the slot indexes correlate. -Meaning, slot 0 in the control data is used to synchronize slot 0 in the sample data. -More information on these slot and the underlying algorithm can be found in :ref:`synchronization_algorithm`. - -.. image:: _assets/lola_slots.drawio.svg - :alt: Relation of control data and sample data - -.. _message_passing_facilities: - -Message Passing Facilities -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The Message Passing facilities, will not be used to synchronize the access to the shared memory segments. -This is done over the control segments. -We utilize message passing for notifications only. -These notifications include: - -- event notification -- partial restart - -This is done, since there is no need to implement an additional notification handling via shared memory, which would -only be possible by using mutexes and condition variables. -The utilization of mutexes would make the implementation of a wait-free algorithms more difficult. - -Instead, we use an OS feature for notification: - -- QNX Message Passing (under QNX) -- Unix Domain Sockets (under Linux) - -As illustrated in the graphic below a process should provide one message passing port to receive data for each supported -ASIL-Level. -In order to ensure that messages received from QM processes will not influence ASIL messages, each message passing port -shall use a custom thread to wait for new messages. -Further, it must be possible to register callbacks for mentioned messages. -These callbacks shall then be invoked in the context of the socket specific thread. -This way we can ensure that messages are received in a serialized manner. - -.. image:: _assets/lola_message_passing.drawio.svg - :alt: Message Passing in LoLa - -.. _shared_memory_handling: - -Shared Memory Handling -^^^^^^^^^^^^^^^^^^^^^^ - -POSIX based operating systems generally support two kinds of shared memory: - -- file-backed -- anonymous - -Former is represented by a file within the file-system, while the latter is not visible directly to other processes. -We decide for former, in order to utilize the filesystem for a simpler service discovery. -In order to avoid fault propagation over restarts of the system, any shared memory communication shall not be -persistent. -Processes will identify shared memory segments over their name. -The name will be commonly known by producers and consumers and deduced by additional parameters like for example service -id and instance id. -When it comes to the granularity of the data stored in the shared memory segments, multiple options can be considered. -We could have one triplet of shared memory segments per process or one triplet of shared memory segments per event -within a service instance. -Former would make the ASIL-Split of segments quite hard, while the latter would explode the number of necessary segments -within the system. -As trade-of we decided to have one triplet of shared memory segments per service instance. - -It is possible to map shared memory segments to a fixed virtual address. -This is highly discouraged by POSIX and leads to undefined behaviour. -Thus, shared memory segments will be mapped to different virtual addresses. -In consequence no raw pointer can be stored within shared memory, since it will be invalid within another process. -Only offset pointer (fancy pointer, relative pointer) shall be stored within shared memory segments. - -The usage of shared memory does not involve the operating system, after shared memory segments are setup. -Thus, the operating system can no longer ensure freedom from interference between processes that have access to these -shared memory regions. -In order to restrict access we use ACL support of the operating system. - -In addition to the restricted permissions, we have to ensure that a corrupted shared memory region cannot influence -other process-local memory regions. -This can be ensured by performing Active Bounds Checking. -So the only way how data corruption could propagate throughout a shared memory region is if a pointer within a shared -memory region points out of it. -Thus, a write operation to such a pointer could forward memory corruption. -The basic idea to overcome such a scenario is, that we check that any pointer stays within the bounds of the shared -memory region. -Since anyhow only offset pointers can be stored in a shared memory region, this active bounds check can be performed -whenever a offset pointer is dereferenced. - -The last possible impact can be on timing. -If another process for example wrongly locks a mutex within the shared memory region and another process would then wait -for this lock, we would end up in a deadlock. -While timing is explicitly not a safety requirement (see :ref:`spec_mixed_criticality`), we still want to strive for -wait-free algorithms to avoid such situations. -Further, avoiding mutexes in our algorithms increases performance since it reduces kernel calls. - -.. _synchronization_algorithm: - -Synchronization Algorithm -^^^^^^^^^^^^^^^^^^^^^^^^^ - -A slot shall contain all necessary meta-information in order to synchronize data access. -This information most certainly needs to include a timestamp to indicate the order of produced data within the slots. -Additionally, a use count is needed, indicating if a slot is currently in use by one process. -The concrete data is implementation defined and must be covered by the detailed design. - -The main idea of the algorithm is that a producer shall always be able to store one new data sample. -If he cannot find a respective slot, this indicates a contract violation, which indicates that a QM process misbehaved. -In such a case, a producer should exclude any QM consumer from the communication. - -This whole idea builds up on the split of shared memory segments by ASIL levels. -This way we can ensure that an QM process will not degrade the ASIL Level for a communication path. -In another case, where we already have a QM producer, it is possible for an ASIL B consumer to consume the QM data. -In this scenario, there is no separate control data for ASIL B, and they instead interact on the control data -for ASIL QM. -This is because, the data is QM and it is impossible for the middleware to apply additional checks to -enhance the quality of data. -This can only be done on application layer level. -Hence, separating QM and ASIL consumers holds no benefit. - -.. _service_discovery: - -Service Discovery -^^^^^^^^^^^^^^^^^ - -The communication framework must be capable to discover available service offers at runtime. -The offered services are differentiated by: - -- service id (a unique identifier per different service interface) -- instance id (a unique identifier per different producer offering the same service interface) -- criticality level -- version (not yet supported, see :ref:`roadmap`) - -To reduce resource consumption we decide against using an approach with a service registry daemon. -Instead we choose to use operating system facilities to achieve a performant service discovery. - -The key technology behind the service discovery is the inotify subsystem of POSIX compliant operating systems. -It allows resource efficient and performant tracking of changes in the filesystem. - -Keeping track of available service instances is left to the operating system. -Producers notify the OS about new service offers by creating a flag file. -Consumers either crawl the filesystem for existing offers or attach an inotify watch to wait for upcoming offers. -Whenever a new file is created, the OS automatically checks for impacted inotify watches and notifies each watch with -an appropriate event. - -Also complex search requests where a consumer wants to know about all service instances with the same service interface, -can be solved efficiently with the inotify subsystem. - -Service discovery is currently fully explicit. -Implicit service discovery for consumers is on our :ref:`roadmap`. -The goal is to handle service discovery transparently wherever possible. - -Partial Restart Capability -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Partial restart capability means, that one of several communication partners may crash at any point in time and will -still be able to start up again and rejoin the communication, without affecting the other communication partners. - -Challenge to overcome -""""""""""""""""""""" - -There is a shared state held in shared memory (the control data), which is maintained by all communication partners -(provider and consumers). -Consumers annotate within this shared state, which data (events/fields) they are currently -consuming (and therefore blocking underlying slots from re-use by the producer). -The provider annotates within this shared state, which slots are currently blocked for data updates that can't be -accessed by consumers. - -When a communication partner crashes, it may leave slots blocked within the shared state. -When it restarts later, it has to reclaim/re-use or free exactly the same slots, it claimed in a previous run. -Not doing so, would lead to resource exhaustion, since the slots would remain blocked indefinitely for either the -producer or consumers. -This requires, that a restarting communication partner knows exactly, which changes it had done to the shared state -previously in order to roll them back again. - -Recovery mechanism -"""""""""""""""""" - -The mechanism to enable the cleanup/recovery of shared state by a restarting communication partner is based -on transaction logs: - -Each consumer and the producer owns a corresponding transaction log, which resides in shared memory. -They annotate what change to the shared state they are going to do. -Creating a transaction log entry means: - -1. Writing a transaction begin marker, which completely describes, which change the upcoming activity will do. -2. Executing the activity in question. -3. Writing a transaction end marker, which annotates, whether the activity in (2) was done or not. - -During the restart of a communication partner, he checks for existing transaction logs in shared memory, which it -created in an earlier run, so that it can roll them back. - -Two scenarios are possible: - -- All transaction log entries are complete (transaction end marker is written). - The communication partner can roll all transactions back and rejoin communication. -- A transaction log entry is incomplete (transaction end marker is missing). - The communication partner is incapable of rolling back his actions fully. - Rejoining the communication would impact other communication partners. - The communication partner is barred from rejoining the communication. - -We reduce the likelihood of the second scenario, by using transactions only when unavoidable and by keeping them short. - -Mock Binding ------------- - -To support users in their testing efforts, the communication framework must provide support for mocking and faking. -Since the public API of mw::com is highly templated, most testing frameworks would reach their limits. -So instead of making the public API directly mockable, we use the binding concept to provide a mock binding. -The mock binding utilizes the GMock framework. - -Interfaces -********** - diff --git a/docs/features/communication/ipc/architecture/feature_architecture.rst b/docs/features/communication/ipc/architecture/feature_architecture.rst deleted file mode 100644 index 36c906a1f3..0000000000 --- a/docs/features/communication/ipc/architecture/feature_architecture.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Feature Architecture -#################### - -Static Architecture -******************* - -.. feat_arc_sta:: Static Architecture - :id: feat_arc_sta__communication__ipc - :security: YES - :status: valid - :safety: ASIL_B - :fulfils: feat_req__ipc__data_loss, feat_req__ipc__time_based_arch, feat_req__ipc__data_driven_arch, feat_req__ipc__request_driven_arch, feat_req__ipc__event_type, feat_req__ipc__method, feat_req__ipc__signal, feat_req__ipc__producer_consumer, feat_req__ipc__service_instance, feat_req__ipc__service_instance_names, feat_req__ipc__versioning, feat_req__ipc__service_location_transparency, feat_req__ipc__stateless_communication, feat_req__ipc__service_instance_granularity, feat_req__ipc__service_discovery, feat_req__ipc__safe_communication, feat_req__ipc__data_corruption, feat_req__ipc__data_reordering, feat_req__ipc__data_repetition, feat_req__ipc__data_loss, feat_req__ipc__asil - :includes: logic_arc_int__communication__ipc - - .. uml:: _assets/stat_arch.puml - :scale: 50 - :align: center - -Dynamic Architecture -******************** - -.. feat_arc_dyn:: Dynamic Architecture - :id: feat_arc_dyn__communication__ipc - :security: YES - :status: valid - :safety: ASIL_B - :fulfils: feat_req__ipc__depl_config_runtime - - .. uml:: _assets/dyn_arch.puml - :scale: 50 - :align: center - -Interfaces -********** - -.. logic_arc_int:: Logical Interface - :id: logic_arc_int__communication__ipc - :security: YES - :safety: ASIL_B - :status: valid - :fulfils: feat_req__ipc__interfaces - -.. needextend:: docname is not None and "communication/ipc/architecture" in docname - :+tags: ipc diff --git a/docs/features/communication/ipc/architecture/_assets/dyn_arch.puml b/docs/features/communication/ipc/docs/architecture/_assets/dyn_arch.puml similarity index 100% rename from docs/features/communication/ipc/architecture/_assets/dyn_arch.puml rename to docs/features/communication/ipc/docs/architecture/_assets/dyn_arch.puml diff --git a/docs/features/communication/ipc/architecture/_assets/lola_message_passing.drawio.svg b/docs/features/communication/ipc/docs/architecture/_assets/lola_message_passing.drawio.svg similarity index 100% rename from docs/features/communication/ipc/architecture/_assets/lola_message_passing.drawio.svg rename to docs/features/communication/ipc/docs/architecture/_assets/lola_message_passing.drawio.svg diff --git a/docs/features/communication/ipc/architecture/_assets/lola_mixed_crit_1_n.drawio.svg b/docs/features/communication/ipc/docs/architecture/_assets/lola_mixed_crit_1_n.drawio.svg similarity index 100% rename from docs/features/communication/ipc/architecture/_assets/lola_mixed_crit_1_n.drawio.svg rename to docs/features/communication/ipc/docs/architecture/_assets/lola_mixed_crit_1_n.drawio.svg diff --git a/docs/features/communication/ipc/architecture/_assets/lola_slots.drawio.svg b/docs/features/communication/ipc/docs/architecture/_assets/lola_slots.drawio.svg similarity index 100% rename from docs/features/communication/ipc/architecture/_assets/lola_slots.drawio.svg rename to docs/features/communication/ipc/docs/architecture/_assets/lola_slots.drawio.svg diff --git a/docs/features/communication/ipc/docs/architecture/index.rst b/docs/features/communication/ipc/docs/architecture/index.rst new file mode 100644 index 0000000000..fc9fa12f3c --- /dev/null +++ b/docs/features/communication/ipc/docs/architecture/index.rst @@ -0,0 +1,224 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _ipc_architecture: + +Architecture +============ + +Overview +-------- + +An brief overview of ipc is described :ref:`here `. + +Description +----------- + +A description of the ipc module is located :ref:`here ` + +.. _ipc_arch_dec: + +Rationale for Architecture Decision +----------------------------------- + +The basic idea of the ipc binding concept is to use two main operating system facilities: + +#. Shared Memory: Shall be used for the heavy lifting of data exchange +#. Message Passing: Shall be used as notification mechanism + +We decided for using two channels since implementing a notification system via shared memory would include the usage of +condition variables. These condition variables would require a mutex. This could lead to the situation that a malicious process could lock the mutex forever and thus destroy any event notification. In general we can say that any kind of notification shall be exchanged via message passing facilities. The section :ref:`ipc_message_passing` below will go into more detail. + +The usage of shared memory has some implications. First, any synchronization regarding thread-safety / process-safety needs to be performed by the user. Second, the memory that is shared between the processes is directly mapped into their virtual address space. This implies that it is easy for a misbehaving process to destroy or manipulate any data within this memory segment. In order to cope with the latter, we split up the shared memory into three segments. + +- First, a segment where only the to-be-exchanged data is provided. + This segment shall be read-only to consumers and writeable by the producer. + This will ensure that nobody besides the producer process can manipulate the provided data. +- The second and third segment shall contain necessary control information for the data segment. + Necessary control information can include atomics that are used to synchronize the access to the data segments. + Since this kind of access requires write access, we split the shared memory segments for control data by ASIL Level. + This way it can be ensured that no low-level ASIL process interferes with higher level ones. + More information on shared memory handling can be found in :ref:`ipc_shared_memory_handling`. + +.. figure:: _assets/lola_mixed_crit_1_n.drawio.svg + :align: center + :name: mixed_criticality_ipc + + Mixed criticality setup for zero-copy IPC + +One of the main ideas in this concept is the split of control data from sample (user) data. In order to ensure a mapping, the shared memory segments are divided into slots. By convention, we then define that the slot indexes correlate. Meaning, slot 0 in the control data is used to synchronize slot 0 in the sample data. More information on these slot and the underlying algorithm can be found in :ref:`ipc_synchronization_algorithm`. + +.. figure:: _assets/lola_slots.drawio.svg + :align: center + :name: relation_slots_ipc + + Relation of control data and sample data + +.. _ipc_stat_arch: + +Static Architecture +------------------- + +The overall static architecture of the ipc module is located + +.. _ipc_message_passing: + +Message Passing Facilities +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Message Passing facilities, will not be used to synchronize the access to the shared memory segments. This is done over the control segments. We utilize message passing for notifications only. These notifications include: + +- event notification +- partial restart + +This is done, since there is no need to implement an additional notification handling via shared memory, which would +only be possible by using mutexes and condition variables. The utilization of mutexes would make the implementation of a wait-free algorithms more difficult. + +Instead, we use an OS feature for notification: + +- QNX Message Passing (under QNX) +- Unix Domain Sockets (under Linux) + +As illustrated in the graphic below a process should provide one message passing port to receive data for each supported +ASIL-Level. In order to ensure that messages received from QM processes will not influence ASIL messages, each message passing port shall use a custom thread to wait for new messages. Further, it must be possible to register callbacks for mentioned messages. These callbacks shall then be invoked in the context of the socket specific thread. +This way we can ensure that messages are received in a serialized manner. + +.. figure:: _assets/lola_message_passing.drawio.svg + :align: center + :name: message_passing_ipc + + Message Passing in LoLa + +.. _ipc_shared_memory_handling: + +Shared Memory Handling +^^^^^^^^^^^^^^^^^^^^^^ + +POSIX based operating systems generally support two kinds of shared memory: + +- file-backed +- anonymous + +Former is represented by a file within the file-system, while the latter is not visible directly to other processes. We decide for former, in order to utilize the filesystem for a simpler service discovery. In order to avoid fault propagation over restarts of the system, any shared memory communication shall not be persistent. +Processes will identify shared memory segments over their name. The name will be commonly known by producers and consumers and deduced by additional parameters like for example service id and instance id. +When it comes to the granularity of the data stored in the shared memory segments, multiple options can be considered. +We could have one triplet of shared memory segments per process or one triplet of shared memory segments per event +within a service instance. Former would make the ASIL-Split of segments quite hard, while the latter would explode the number of necessary segments within the system. As trade-of we decided to have one triplet of shared memory segments per service instance. + +It is possible to map shared memory segments to a fixed virtual address. This is highly discouraged by POSIX and leads to undefined behaviour. Thus, shared memory segments will be mapped to different virtual addresses. In consequence no raw pointer can be stored within shared memory, since it will be invalid within another process. Only offset pointer (fancy pointer, relative pointer) shall be stored within shared memory segments. + +The usage of shared memory does not involve the operating system, after shared memory segments are setup. Thus, the operating system can no longer ensure freedom from interference between processes that have access to these shared memory regions. In order to restrict access we use ACL support of the operating system. + +In addition to the restricted permissions, we have to ensure that a corrupted shared memory region cannot influence +other process-local memory regions. This can be ensured by performing Active Bounds Checking. +So the only way how data corruption could propagate throughout a shared memory region is if a pointer within a shared +memory region points out of it. Thus, a write operation to such a pointer could forward memory corruption. +The basic idea to overcome such a scenario is, that we check that any pointer stays within the bounds of the shared +memory region. Since anyhow only offset pointers can be stored in a shared memory region, this active bounds check can be performed whenever a offset pointer is dereferenced. + +The last possible impact can be on timing. If another process for example wrongly locks a mutex within the shared memory region and another process would then wait for this lock, we would end up in a deadlock. While timing is explicitly not a safety requirement (see :ref:`com_mixed_criticality`), we still want to strive for +wait-free algorithms to avoid such situations. Further, avoiding mutexes in our algorithms increases performance since it reduces kernel calls. + +.. _ipc_synchronization_algorithm: + +Synchronization Algorithm +^^^^^^^^^^^^^^^^^^^^^^^^^ + +A slot shall contain all necessary meta-information in order to synchronize data access. This information most certainly needs to include a timestamp to indicate the order of produced data within the slots. Additionally, a use count is needed, indicating if a slot is currently in use by one process. The concrete data is implementation defined and must be covered by the detailed design. + +The main idea of the algorithm is that a producer shall always be able to store one new data sample. If he cannot find a respective slot, this indicates a contract violation, which indicates that a QM process misbehaved. In such a case, a producer should exclude any QM consumer from the communication. + +This whole idea builds up on the split of shared memory segments by ASIL levels. This way we can ensure that an QM process will not degrade the ASIL Level for a communication path. In another case, where we already have a QM producer, it is possible for an ASIL B consumer to consume the QM data. In this scenario, there is no separate control data for ASIL B, and they instead interact on the control data for ASIL QM. This is because, the data is QM and it is impossible for the middleware to apply additional checks to enhance the quality of data. This can only be done on application layer level. Hence, separating QM and ASIL consumers holds no benefit. + +.. _ipc_service_discovery: + +Service Discovery +^^^^^^^^^^^^^^^^^ + +The communication framework must be capable to discover available service offers at runtime. The offered services are differentiated by: + +- service id (a unique identifier per different service interface) +- instance id (a unique identifier per different producer offering the same service interface) +- criticality level +- version (not yet supported, see :ref:`ipc_roadmap`) + +To reduce resource consumption we decide against using an approach with a service registry daemon. Instead we choose to use operating system facilities to achieve a performant service discovery. + +The key technology behind the service discovery is the inotify subsystem of POSIX compliant operating systems. It allows resource efficient and performant tracking of changes in the filesystem. + +Keeping track of available service instances is left to the operating system. Producers notify the OS about new service offers by creating a flag file. Consumers either crawl the filesystem for existing offers or attach an inotify watch to wait for upcoming offers. Whenever a new file is created, the OS automatically checks for impacted inotify watches and notifies each watch with an appropriate event. + +Also complex search requests where a consumer wants to know about all service instances with the same service interface, +can be solved efficiently with the inotify subsystem. + +Service discovery is currently fully explicit. Implicit service discovery for consumers is on our :ref:`ipc_roadmap`. The goal is to handle service discovery transparently wherever possible. + +Partial Restart Capability +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Partial restart capability means, that one of several communication partners may crash at any point in time and will +still be able to start up again and rejoin the communication, without affecting the other communication partners. + +Challenge to overcome +''''''''''''''''''''' + +There is a shared state held in shared memory (the control data), which is maintained by all communication partners +(provider and consumers). Consumers annotate within this shared state, which data (events/fields) they are currently +consuming (and therefore blocking underlying slots from re-use by the producer). The provider annotates within this shared state, which slots are currently blocked for data updates that can't be accessed by consumers. + +When a communication partner crashes, it may leave slots blocked within the shared state. When it restarts later, it has to reclaim/re-use or free exactly the same slots, it claimed in a previous run. Not doing so, would lead to resource exhaustion, since the slots would remain blocked indefinitely for either the producer or consumers. +This requires, that a restarting communication partner knows exactly, which changes it had done to the shared state +previously in order to roll them back again. + +Recovery mechanism +'''''''''''''''''' + +The mechanism to enable the cleanup/recovery of shared state by a restarting communication partner is based +on transaction logs: + +Each consumer and the producer owns a corresponding transaction log, which resides in shared memory. They annotate what change to the shared state they are going to do. Creating a transaction log entry means: + +#. Writing a transaction begin marker, which completely describes, which change the upcoming activity will do. +#. Executing the activity in question. +#. Writing a transaction end marker, which annotates, whether the activity in (2) was done or not. + +During the restart of a communication partner, he checks for existing transaction logs in shared memory, which it +created in an earlier run, so that it can roll them back. + +Two scenarios are possible: + +- All transaction log entries are complete (transaction end marker is written). + The communication partner can roll all transactions back and rejoin communication. +- A transaction log entry is incomplete (transaction end marker is missing). + The communication partner is incapable of rolling back his actions fully. + Rejoining the communication would impact other communication partners. + The communication partner is barred from rejoining the communication. + +We reduce the likelihood of the second scenario, by using transactions only when unavoidable and by keeping them short. + +.. _ipc_dyn_arch: + +Dynamic Architecture +-------------------- + +.. feat_arc_dyn:: Dynamic Architecture + :id: feat_arc_dyn__communication__ipc + :security: YES + :status: valid + :safety: ASIL_B + :fulfils: feat_req__com__depl_config_runtime + + .. uml:: _assets/dyn_arch.puml + :scale: 50 + :align: center diff --git a/docs/features/communication/ipc/docs/requirements/index.rst b/docs/features/communication/ipc/docs/requirements/index.rst new file mode 100644 index 0000000000..e0efe74dbd --- /dev/null +++ b/docs/features/communication/ipc/docs/requirements/index.rst @@ -0,0 +1,59 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _ipc_requirements: + +Requirements +============ + +.. feat_req:: Zero-Copy Approach + :id: feat_req__ipc__zero_copy + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data + :status: valid + + IPC communication shall be possible without copying to-be-transferred data. + +.. feat_req:: IPC Confidentiality + :id: feat_req__ipc__confidentiality + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__communication__inter_process + :status: valid + + The IPC binding shall ensure confidentiality of its communication. + +.. feat_req:: IPC Integrity + :id: feat_req__ipc__integrity + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__communication__inter_process + :status: valid + + The IPC binding shall ensure integrity of its communication. + +.. feat_req:: IPC Availability + :id: feat_req__ipc__availability + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__communication__inter_process + :status: valid + + The IPC binding shall ensure availability of its communication, so that the availability is independent per + criticality level. diff --git a/docs/features/communication/ipc/roadmap.rst b/docs/features/communication/ipc/docs/roadmap.rst similarity index 98% rename from docs/features/communication/ipc/roadmap.rst rename to docs/features/communication/ipc/docs/roadmap.rst index 51c0e17025..8fff481af8 100644 --- a/docs/features/communication/ipc/roadmap.rst +++ b/docs/features/communication/ipc/docs/roadmap.rst @@ -12,7 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _roadmap: +.. _ipc_roadmap: Roadmap ======= diff --git a/docs/features/communication/ipc/safety_planning/index.rst b/docs/features/communication/ipc/docs/safety_planning/index.rst similarity index 96% rename from docs/features/communication/ipc/safety_planning/index.rst rename to docs/features/communication/ipc/docs/safety_planning/index.rst index 86e4cd0bd6..c60d1fc885 100644 --- a/docs/features/communication/ipc/safety_planning/index.rst +++ b/docs/features/communication/ipc/docs/safety_planning/index.rst @@ -12,6 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +.. _safety_planning_ipc: + Safety Planning ############### @@ -32,8 +34,8 @@ Inter-process Communication Safety Work Products - :need:`PROCESS_gd_temp__change__feature_request` - :ndf:`copy('status', need_id='PROCESS_gd_temp__change__feature_request')` - `#69 `_ - - :need:`doc__ipc` - - :ndf:`copy('status', need_id='doc__ipc')` + - :need:`doc__com_ipc` + - :ndf:`copy('status', need_id='doc__com_ipc')` * - :need:`PROCESS_wp__requirements__feat` - :need:`PROCESS_gd_temp__req__feat_req` diff --git a/docs/features/communication/ipc/index.rst b/docs/features/communication/ipc/index.rst index f069d70579..f3239c660b 100644 --- a/docs/features/communication/ipc/index.rst +++ b/docs/features/communication/ipc/index.rst @@ -12,26 +12,24 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _ipc_feature: +.. _communication_ipc: Inter-process Communication ########################### .. document:: Inter-process Communication - :id: doc__ipc + :id: doc__com_ipc :status: valid - :safety: ASIL_B :tags: contribution_request, feature_request - .. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: :hidden: - architecture/index.rst - requirements/index.rst - safety_planning/index.rst - roadmap.rst - + docs/**/index + docs/roadmap Feature flag ============ @@ -40,357 +38,63 @@ To activate this feature, use the following feature flag: ``experimental_ipc`` -Abstract +.. _ipc_overview: + +Overview ======== This contribution describes a framework to exchange information between processes. This framework includes: -- an abstraction layer to enable different communication mechanisms - a communication mechanism that enables zero-copy communication +- a mock binding for testing -The abstraction layer is designed in a way to ensure full testability for an end-user, while enabling runtime selection -of the underlying communication mechanism. -It provides the user with a high-level API to focus on the content of information – and not on low-level synchronization -primitives. -The proposed communication mechanism (called LoLa) is optimized for micro-kernel operating systems (like e.g. QNX). By +The proposed IPC mechanism (called LoLa) is optimized for micro-kernel operating systems (like e.g. QNX). By utilizing shared memory, it enables low latency communication also for mixed-criticality systems (e.g. processes of different safety integrity level). The possibility for mixed-criticality systems is especially enabled by certain implementation choices and safety mechanisms that will continue to ensure freedom from interference between separate processes. -.. _Motivation: - -Motivation -========== - -S-CORE is targeting high-performance automotive systems with safety impact. -In general, these systems consist of multiple processes that are executed on an operating system. -To fulfill the system needs, these processes need to exchange information in most of the cases. - -The communication framework is not a one-fits-all. -For example, it does not replace a standardized platform API that an application links against. - -Key aspects of S-CORE and therefore also the IPC communication framework are: - -1. High cohesion and loose coupling -2. Mixed-criticality safety systems -3. Performance - -In the following we will explain and argue each of these three different aspects. Further secondary aspects will follow -in the section :ref:`Specification` where we also formalize all aspects. - -High cohesion and loose coupling --------------------------------- - -Complex systems require high cohesion and loose coupling to remain maintainable. -The benefit of loose coupling is to limit the effect of changes throughout the system. -Key to achieve this is stability of interfaces. +.. _ipc_description: -Since the communication of a module is also part of its interface, we must consider its stability. -How stable an interface is, largely depends on the implementation reachable through it. -This means, the communication framework can not provide stability on its own. -It can only provide the necessary tools for developers to consider the stability when changing the interface or -implementation. +Description +=========== -.. _mot_mixed_criticality: +As S-CORE is targeting high-performance ECUs application will run on different processes of the OS. To fulfill the system needs, these processes need to exchange information. The IPC framework is not a one-fits-all. For example, it does not replace a standardized platform API that an application links against. -Mixed-Criticality safety systems --------------------------------- +For the IPC framework also the Key- and Secondary Aspects of the general communication framework are valid as mentioned in :ref:`com_rationale` -In complex safety-critical systems, applications often have different criticality. -Communication happens not only on the same criticality level but also between different criticality levels. +The basic idea of the ipc binding concept is to use two main operating system facilities: -For example, a service with low-criticality may provide data to a highly critical application. -Or the reverse could be the case, where a less critical application depends on data produced by a highly critical one. -More complex scenarios are also possible, where the same data is consumed by multiple recipients with different -criticality. +#. Shared Memory: Shall be used for the heavy lifting of data exchange +#. Message Passing: Shall be used as notification mechanism -Hence, it is crucial that applications can not only safely communicate on the same criticality level. -They must be able to also safely communicate between different criticality levels. +A more detailed description is provided in the architecture chapter :ref:`ipc_architecture` -Support for mixed criticality is a core feature of a communication framework. Hence, it greatly impacts architectural -decisions and influences many other aspects. One of them being performance, which is the third primary aspect of a -communication framework. - -Performance ------------ - -In the recent years high-performance automotive systems rely more and more on communication of huge amounts of data. -This communication must be performant, to enable decomposition of the system. -With ever increasing complexity of the tasks automotive systems must tackle, this trend will continue in the future. -Hence, architectural decisions for the communication framework must ensure scalable performance. - -In general, good scalable performance can be decomposed into two aspects: - -1. High throughput -2. Low latency - -To achieve both, only zero-copy approaches are feasible. -Further, reliable low-latency communication is only possible with appropriate scheduling. -Meaning, if a consumer is not scheduled when he receives an event, the latency of the communication is out of the hand -of the communication framework. -Thus, the communication framework must be capable to interact with the scheduler to influence the scheduling behavior. - -For mixed-criticality safety systems this means, that the original non-duplicated data must be provided to consumers -with different criticality levels. - -The previous three key aspects and further aspects are formalized in the section :ref:`Specification`. - -Rationale -========= - -.. _Specification: +.. _ipc_specification: Specification ============= -To provide a clear picture of the base requirements to an IPC communication framework, we formalize the primary and -secondary aspects in this section. For aspects that are mentioned for the first time, we also provide a rationale. -For the previously presented primary aspects, please refer to the section :ref:`Motivation` for the rationale. - -Before we can discuss the primary aspects, we must define what basic communication patterns the framework supports. -S-CORE defines in its stakeholder requirements different architectures that must be supported by the communication -framework. -This leads to the three requirements: - -9. :need:`feat_req__ipc__time_based_arch` -10. :need:`feat_req__ipc__data_driven_arch` -11. :need:`feat_req__ipc__request_driven_arch` - -Based on this, the basic communication elements consist of: - -- :need:`feat_req__ipc__event_type` -- :need:`feat_req__ipc__method` -- :need:`feat_req__ipc__signal` - -Since often communication regarding a specific feature consists of many of these elements, we allow grouping of them -through communication interfaces (:need:`feat_req__ipc__interfaces`). - -To allow more flexible scheduling of the system and as a prerequisite of :need:`feat_req__ipc__time_based_arch`, -the communication framework must support caching: :need:`feat_req__ipc__producer_consumer` - -Further, we promote stateless communication :need:`feat_req__ipc__stateless_communication` to simplify the communication -logic both in the framework as well as the user code. - -With the basic syntax for communication covered, we now discuss the key aspects a communication framework must fulfill. - -We coin the term "Service instance" to refer to an entity that offers functionality through a communication interface -(:need:`feat_req__ipc__service_instance`). - -In general, we put no restrains in how service instances are grouped in the architecture -(:need:`feat_req__ipc__service_instance_granularity`). - -High cohesion and loose coupling --------------------------------- - -As discussed in the motivation, versioning of communication interfaces is key for a communication framework to promote -high cohesion and loose coupling. - -Version compatibility can be separated into syntactic compatibility and semantic compatibility. -Communication partners are only capable to communicate properly with each other, if they are compatible in both domains. -Thus, a versioning concept must consider both syntax and semantics. -Therefore, it does not suffice to only version communication interfaces. -Similarly, only versioning the behavior of the functionality behind an interface is not enough. - -Instead, we define a single version scheme over both syntax and semantics of a service instance. -Meaning, whenever the service instance has a syntactic or semantic change, the version must be bumped. - -This leads to the conclusion that the version is associated to the service instance (:need:`feat_req__ipc__versioning`). - -It is impossible to define a global versioning scheme over all protocols, with their significantly differing -capabilities in that regard. Thus, version compatibility ranges must be supplied per protocol -(:need:`feat_req__ipc__versioning`). - -Additional to versioning, loose coupling also requires that the communication partners are unaware of where their -counterpart resides (:need:`feat_req__ipc__service_location_transparency`). -This implies, that communication partners are discovered dynamically at runtime -(:need:`feat_req__ipc__service_discovery`). -Discovery of communication partners must consider their compatibility based on the versioning concept. - -To retain loose coupling, the public API of the communication framework shall treat discovery implicitly without -unneeded user involvement (:need:`feat_req__ipc__service_discovery`). -Further, service discovery is based on a naming scheme where each service instance is associated to one or more names -(:need:`feat_req__ipc__service_instance_names`). - -.. _spec_mixed_criticality: - -Mixed-Criticality safety systems --------------------------------- - -As discussed in the motivation the communication framework shall support mixed-criticality safety systems -:need:`feat_req__ipc__safe_communication`. - -In the light of mixed-criticality safety systems and based on the failure modes for communication in the ISO26262, -the communication framework gains four additional requirements: - -1. :need:`feat_req__ipc__data_corruption` -2. :need:`feat_req__ipc__data_reordering` -3. :need:`feat_req__ipc__data_repetition` -4. :need:`feat_req__ipc__data_loss` - -The communication framework does not take timing related failure modes into account, since the overall stack must -consider such failure modes on a more generic level. +For IPC also the specification of communication applies: :ref:`com_specification` -Performance ------------ +Architecture +------------ -Based on the discussion in the motivation, the specific use cases can be condensed to the overall requirement to support -zero-copy IPC (:need:`feat_req__ipc__zero_copy`). +The architecure of communication is diplayed :ref:`here` -For now, there is no requirement to support zero-copy communication for other protocols. -While this may be of interest in the future, it remains for now out of scope. +Requirements +------------ -User friendly API for information exchange ------------------------------------------- +The requirements for communication are listed :ref:`here` -Programming languages have their own feature set and idioms. -It is crucial for any library that it seamlessly integrates into both. -This means, wherever possible and meaningful, infrastructure of the programming language and accompanying standard -libraries shall be reused. -Further, a developer used to the programming language shall have no problems understanding the API. -It should feel natural to use. -This includes error handling, which shall follow one of the error handling concepts of the programming language. - -1. :need:`feat_req__ipc__lang_idioms` -2. :need:`feat_req__ipc__lang_infra` - -Since S-CORE supports multiple programming languages (see :need:`stkh_req__dev_experience__prog_languages`), this leads to multiple APIs that might -diverge significantly from each other, but provide the same feature set to the user. -To support something like this, without reimplementing the full communication stack in both languages, an abstraction -layer within the communication framework is unavoidable. - -:need:`feat_req__ipc__multi_lang` - -Full testability for the user facing API ----------------------------------------- - -Our users will be required to proof certain coverage metrics, like line coverage or MC/DC coverage. -For them to reach full coverage, they need to be easily able to mock or fake parts of the communication systems in their -unit tests. -Most of the current solutions (e.g. ara::com) keep this outside their requirements. -This forces the users to introduce an additional abstraction layer over the communication framework to inject test -doubles. -This is additional work for the user, and abstraction layers come with a certain cost in runtime and maintenance. -Our goal is to provide an API that requires no additional abstraction layer over the communication framework. - -:need:`feat_req__ipc__testability_mock_api` - -In some test scenarios users must fake communication. -Instead of mocking the fine-granular behavior of the framework, users shall be able to simulate communication simply by -providing an implementation of the communication partner in the test environment. For IPC this does not require big -architectural decisions. In the light of a robust API that also supports communication between multiple hosts, -this can be achieved through multi-binding support. - -:need:`feat_req__ipc__testability_fake_binding` - -.. _multi_binding_support: - -Multi-binding support ---------------------- - -In the beginning, S-CORE will only provide inter-process communication. -But this will not suffice for later. -A communication framework for high-performance automotive systems with safety impact will require support for -communication to other VMs or hosts. - -Following the idea of service location transparency, we introduce multi-binding support. -A binding is responsible of translating requests from the user to the respective protocol used for communication. -It may do so by directly performing the communication into the chosen protocol without intermediate protocols inbetween. -But it can also use a gateway approach where it forwards the communication using a different protocol (e.g. IPC) to a -gateway which then performs the translation between protocols. - -:need:`feat_req__ipc__multi_binding_support` - -To enable service location transparency, the public API is designed to be binding-agnostic. -If the binding is exchanged, the public API remains syntactically and semantically unchanged. - -:need:`feat_req__ipc__binding_agnostic_api` - -The framework forwards requests from the public API to the appropriate binding of the service instance. -Bindings are specified in the deployment configuration. - -:need:`feat_req__ipc__multi_binding_depl` - -Some possible bindings are: - -- IPC (see :need:`stkh_req__communication__inter_process`) -- SOME/IP (see :need:`stkh_req__communication__supported_net`) -- DDS (see :need:`stkh_req__communication__supported_net`) -- fake binding (for testing) - -Dynamic deployment at runtime ------------------------------ - -In the light of safety, security and startup requirements, `Service discovery` without some deployment information is -not ideal. -For this reason, most implementations prefer a limited `Service discovery` and supply partial deployment information -in advance. -We too provide partial deployment information through configuration files read at runtime. -This information is enriched through a runtime `Service discovery`. - -:need:`feat_req__ipc__depl_config_runtime` - -Tracing -------- - -Based on :need:`stkh_req__dev_experience__tracing_of_comm` the communication framework must support tracing of communication events. -In a framework with multiple bindings, this requires a zero-copy binding-agnostic tracing solution in the abstraction -layer. - -:need:`feat_req__ipc__tracing` - -Backwards Compatibility -======================= - -As there is currently no previous solution for communication in S-CORE, no backwards compatibility is required. +.. _ipc_security: Security Impact -=============== - -Security of communication is important for the security of the overall system. -To efficiently handle security with the least amount of overhead, each binding must determine the best security approach -for its circumstances. - -Depending on the binding, the security approach may achieve different -`security goals `_. - -To provide users a generic concept of security configuration on the level of interfaces, the chosen solution of every -binding must map at least to an Access Control List (ACL) concept, but may have additional deployment configuration -options. - -The ACL of each service instance is defined in the deployment configuration of producer and consumer. - -- :need:`feat_req__ipc__acl_placement` -- :need:`feat_req__ipc__acl_per_service_instance` - -Entries in the ACL of: - -- the producer list the allowed consumers (:need:`feat_req__ipc__acl_for_producer`) -- the consumer list the allowed producers (:need:`feat_req__ipc__acl_for_consumer`) - -IPC Security Goals ------------------- - -The security approach of the IPC binding achieves the security goals: - -- confidentiality (:need:`feat_req__ipc__confidentiality`) -- integrity (:need:`feat_req__ipc__integrity`) -- availability (per criticality-level) (:need:`feat_req__ipc__acl_placement`) - -Safety Impact -============= - -The safety impact was already exhaustively covered in :ref:`mot_mixed_criticality` and :ref:`spec_mixed_criticality`. - -Overall, the communication framework supports use cases up to ASIL-B (:need:`feat_req__ipc__asil`). -Future extension to ASIL-D use cases is feasible but not in scope for now. - -License Impact -============== - -[How could the copyright impacted by the license of the new contribution?] +--------------- +In addition to the security impact of :ref:`commnication` the IPC binding achieves the security goals: -How to Teach This -================= +- :need:`confidentiality ` +- :need:`integrity ` +- :need:`availability ` (per criticality-level) diff --git a/docs/features/communication/modules/baselibs/index.rst b/docs/features/communication/modules/baselibs/index.rst new file mode 100644 index 0000000000..ddd5429de3 --- /dev/null +++ b/docs/features/communication/modules/baselibs/index.rst @@ -0,0 +1,36 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Baselibs Module +############### + +.. mod_view_sta:: Baselibs + :id: mod_view_sta__baselibs__baselibs + :includes: comp_arc_sta__baselibs__json, comp_arc_sta__baselibs__message_passing, comp_arc_sta__baselibs__memory_shared + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Components +========== + +.. toctree:: + :titlesonly: + + json_component_architecture + memory_shared_component_architecture + message_passing_component_architecture diff --git a/docs/features/communication/modules/baselibs/json_component_architecture.rst b/docs/features/communication/modules/baselibs/json_component_architecture.rst new file mode 100644 index 0000000000..270bf0b0a9 --- /dev/null +++ b/docs/features/communication/modules/baselibs/json_component_architecture.rst @@ -0,0 +1,48 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +JSON Component Architecture +=========================== + +.. comp_arc_sta:: JSON + :id: comp_arc_sta__baselibs__json + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__baselibs__json + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int:: JSON Parser + :id: logic_arc_int__baselibs__json + :security: YES + :safety: ASIL_B + :status: valid + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: Parse + :id: logic_arc_int_op__baselibs__fromfile + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__json diff --git a/docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst b/docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst new file mode 100644 index 0000000000..74ba799b12 --- /dev/null +++ b/docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst @@ -0,0 +1,64 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Memory Shared Component Architecture +==================================== + +.. comp_arc_sta:: Memory Shared + :id: comp_arc_sta__baselibs__memory_shared + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__baselibs__memory_shared + :uses: logic_arc_int__os__fcntl, logic_arc_int__os__stat, logic_arc_int__os__mmap + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int:: Memory Shared + :id: logic_arc_int__baselibs__memory_shared + :security: YES + :safety: ASIL_B + :status: valid + +.. logic_arc_int_op:: Open + :id: logic_arc_int_op__baselibs__open + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__memory_shared + +.. logic_arc_int_op:: Update + :id: logic_arc_int_op__baselibs__update + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__memory_shared + +.. logic_arc_int_op:: Lock + :id: logic_arc_int_op__baselibs__lock + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__memory_shared + +.. logic_arc_int_op:: Set Permissions + :id: logic_arc_int_op__baselibs__set_perm + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__memory_shared diff --git a/docs/features/communication/modules/baselibs/message_passing_component_architecture.rst b/docs/features/communication/modules/baselibs/message_passing_component_architecture.rst new file mode 100644 index 0000000000..40070ca6c1 --- /dev/null +++ b/docs/features/communication/modules/baselibs/message_passing_component_architecture.rst @@ -0,0 +1,44 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Message Passing Component Architecture +====================================== + +.. comp_arc_sta:: Message Passing + :id: comp_arc_sta__baselibs__message_passing + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__baselibs__message_passing + :uses: logic_arc_int__os__message_passing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + + +.. logic_arc_int:: Message Passing + :id: logic_arc_int__baselibs__message_passing + :security: YES + :safety: ASIL_B + :status: valid + +.. logic_arc_int_op:: Send Message + :id: logic_arc_int_op__baselibs__mp_register + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__baselibs__message_passing diff --git a/docs/features/communication/modules/communication/configuration_component_architecture.rst b/docs/features/communication/modules/communication/configuration_component_architecture.rst new file mode 100644 index 0000000000..1820d04fdf --- /dev/null +++ b/docs/features/communication/modules/communication/configuration_component_architecture.rst @@ -0,0 +1,29 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Frontend Architecture +********************* + +.. comp_arc_sta:: Lola Configuration + :id: comp_arc_sta__com__configuration + :security: YES + :safety: ASIL_B + :status: valid + :uses: logic_arc_int__logging__logging + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} diff --git a/docs/features/communication/modules/communication/frontent_component_architecture.rst b/docs/features/communication/modules/communication/frontent_component_architecture.rst new file mode 100644 index 0000000000..23e9c3cf69 --- /dev/null +++ b/docs/features/communication/modules/communication/frontent_component_architecture.rst @@ -0,0 +1,86 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Frontend Architecture +********************* + +.. comp_arc_sta:: mw::com Frontend + :id: comp_arc_sta__com__frontend + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__communication__user + :uses: logic_arc_int__logging__logging, logic_arc_int__tracing__tracing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int_op:: Initialize + :id: logic_arc_int_op__com__initialize + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: Offer Service + :id: logic_arc_int_op__com__offer_service + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: Update + :id: logic_arc_int_op__com__update + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: Send + :id: logic_arc_int_op__com__send + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: StartFindService + :id: logic_arc_int_op__com__startfindserv + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: CreateProxy + :id: logic_arc_int_op__com__createproxy + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: Subscribe + :id: logic_arc_int_op__com__subscribe + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user + +.. logic_arc_int_op:: GetNewSamples + :id: logic_arc_int_op__com__getnewsamples + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__communication__user diff --git a/docs/features/communication/modules/communication/index.rst b/docs/features/communication/modules/communication/index.rst new file mode 100644 index 0000000000..370d9af53a --- /dev/null +++ b/docs/features/communication/modules/communication/index.rst @@ -0,0 +1,41 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Communication Module +#################### + +.. mod_view_sta:: Communication + :id: mod_view_sta__com__communication + :includes: comp_arc_sta__com__configuration, comp_arc_sta__com__ipc_binding, comp_arc_sta__com__mock_binding, comp_arc_sta__com__frontend + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + comp_arc_sta__com__ipc_binding -r[hidden]-> comp_arc_sta__com__frontend + comp_arc_sta__com__frontend -r[hidden]-> comp_arc_sta__com__mock_binding + comp_arc_sta__com__mock_binding -r[hidden]-> comp_arc_sta__com__configuration + logic_arc_int__tracing__tracing -r[hidden]-> logic_arc_int__logging__logging + +Components +========== + +.. toctree:: + :titlesonly: + + configuration_component_architecture + frontent_component_architecture + ipc_binding_architecture + mock_binding_architecture diff --git a/docs/features/communication/modules/communication/ipc_binding_architecture.rst b/docs/features/communication/modules/communication/ipc_binding_architecture.rst new file mode 100644 index 0000000000..5453f1083c --- /dev/null +++ b/docs/features/communication/modules/communication/ipc_binding_architecture.rst @@ -0,0 +1,29 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +IPC Binding Architecture +************************ + +.. comp_arc_sta:: IPC Binding + :id: comp_arc_sta__com__ipc_binding + :security: YES + :safety: ASIL_B + :status: valid + :uses: logic_arc_int__logging__logging, logic_arc_int__tracing__tracing, logic_arc_int__baselibs__memory_shared, logic_arc_int__baselibs__message_passing, logic_arc_int__baselibs__json + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} diff --git a/docs/features/communication/modules/communication/mock_binding_architecture.rst b/docs/features/communication/modules/communication/mock_binding_architecture.rst new file mode 100644 index 0000000000..18d736175f --- /dev/null +++ b/docs/features/communication/modules/communication/mock_binding_architecture.rst @@ -0,0 +1,29 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Mock Binding Architecture +************************* + +.. comp_arc_sta:: Mock binding + :id: comp_arc_sta__com__mock_binding + :security: YES + :safety: ASIL_B + :status: valid + :uses: logic_arc_int__logging__logging + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} diff --git a/docs/features/communication/modules/index.rst b/docs/features/communication/modules/index.rst new file mode 100644 index 0000000000..1b89a0130c --- /dev/null +++ b/docs/features/communication/modules/index.rst @@ -0,0 +1,22 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Modules +======== + +.. toctree:: + :maxdepth: 1 + :glob: + + */index diff --git a/docs/features/communication/modules/logging/index.rst b/docs/features/communication/modules/logging/index.rst new file mode 100644 index 0000000000..65e65f6a0b --- /dev/null +++ b/docs/features/communication/modules/logging/index.rst @@ -0,0 +1,61 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Logging Module +############## + +.. mod_view_sta:: Logging + :id: mod_view_sta__logging__logging + :includes: comp_arc_sta__logging__logging + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Component Architecture +---------------------- + +.. comp_arc_sta:: Logging + :id: comp_arc_sta__logging__logging + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__logging__logging + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int:: Logging + :id: logic_arc_int__logging__logging + :security: YES + :safety: ASIL_B + :status: valid + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: Log + :id: logic_arc_int_op__logging__isenabled + :security: YES + :safety: QM + :status: valid + :included_by: logic_arc_int__logging__logging diff --git a/docs/features/communication/ipc/architecture/index.rst b/docs/features/communication/modules/os/index.rst similarity index 59% rename from docs/features/communication/ipc/architecture/index.rst rename to docs/features/communication/modules/os/index.rst index 667b01423c..3191590cd1 100644 --- a/docs/features/communication/ipc/architecture/index.rst +++ b/docs/features/communication/modules/os/index.rst @@ -1,6 +1,6 @@ .. # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation + # Copyright (c) 2025 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,15 +12,24 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Architecture -############# +OS Module +######### -.. note:: - For now we store the component architecture in the feature tree, because multi-repo docs are not yet supported. - Once this support becomes available the component architecture will be moved to the module. +.. mod_view_sta:: OS + :id: mod_view_sta__os__os + :includes: comp_arc_sta__os__libc, comp_arc_sta__os__message_passing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Components +========== .. toctree:: :titlesonly: - feature_architecture - component_architecture + libc_component_architecture + message_passing_architecture diff --git a/docs/features/communication/modules/os/libc_component_architecture.rst b/docs/features/communication/modules/os/libc_component_architecture.rst new file mode 100644 index 0000000000..c4fa04a805 --- /dev/null +++ b/docs/features/communication/modules/os/libc_component_architecture.rst @@ -0,0 +1,147 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +libc +==== + +.. comp_arc_sta:: libc + :id: comp_arc_sta__os__libc + :security: YES + :safety: ASIL_B + :status: valid + :satisfies: + :implements: logic_arc_int__os__fcntl, logic_arc_int__os__stat, logic_arc_int__os__mmap + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int:: fcntl + :id: logic_arc_int__os__fcntl + :security: YES + :safety: ASIL_B + :status: valid + + File Control + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: Open + :id: logic_arc_int_op__os__open + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__fcntl + +.. logic_arc_int_op:: POSIX fallocate + :id: logic_arc_int_op__os__fallocate + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__fcntl + +.. logic_arc_int_op:: Flock + :id: logic_arc_int_op__os__flock + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__fcntl + +.. logic_arc_int:: mmap + :id: logic_arc_int__os__mmap + :security: YES + :safety: ASIL_B + :status: valid + + Memory Mapping + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: SHM Open + :id: logic_arc_int_op__os__shm_open + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__mmap + +.. logic_arc_int_op:: SHM Unlink + :id: logic_arc_int_op__os__shm_unlink + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__mmap + +.. logic_arc_int:: stat + :id: logic_arc_int__os__stat + :security: YES + :safety: ASIL_B + :status: valid + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: fstat + :id: logic_arc_int_op__os__fstat + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat + +.. logic_arc_int_op:: mkdir + :id: logic_arc_int_op__os__mkdir + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat + +.. logic_arc_int_op:: chmod + :id: logic_arc_int_op__os__chmod + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat + +.. logic_arc_int_op:: fchmod + :id: logic_arc_int_op__os__fchmod + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat + +.. logic_arc_int_op:: umask + :id: logic_arc_int_op__os__umask + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat + +.. logic_arc_int_op:: fcomask + :id: logic_arc_int_op__os__fcomask + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__os__stat diff --git a/docs/features/communication/modules/os/message_passing_architecture.rst b/docs/features/communication/modules/os/message_passing_architecture.rst new file mode 100644 index 0000000000..6f0c9e354b --- /dev/null +++ b/docs/features/communication/modules/os/message_passing_architecture.rst @@ -0,0 +1,62 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Message Passing Component +========================= + +.. comp_arc_sta:: QNX::Message Passing + :id: comp_arc_sta__os__message_passing + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__os__message_passing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +.. logic_arc_int:: OS::Message Passing + :id: logic_arc_int__os__message_passing + :security: YES + :safety: ASIL_B + :status: valid + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: Reply + :id: logic_arc_int_op__os__reply + :security: YES + :safety: QM + :status: valid + :included_by: logic_arc_int__os__message_passing + +.. logic_arc_int_op:: Notify + :id: logic_arc_int_op__os__notify + :security: YES + :safety: QM + :status: valid + :included_by: logic_arc_int__os__message_passing + +.. logic_arc_int_op:: RequestDisconnect + :id: logic_arc_int_op__os__requestdisconnect + :security: YES + :safety: QM + :status: valid + :included_by: logic_arc_int__os__message_passing diff --git a/docs/features/communication/modules/tracing/index.rst b/docs/features/communication/modules/tracing/index.rst new file mode 100644 index 0000000000..e946160387 --- /dev/null +++ b/docs/features/communication/modules/tracing/index.rst @@ -0,0 +1,49 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Tracing Module +############## + +.. mod_view_sta:: Tracing + :id: mod_view_sta__tracing__tracing + :includes: comp_arc_sta__tracing__tracing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Tracing Component Architecture +============================== + +.. comp_arc_sta:: Tracing + :id: comp_arc_sta__tracing__tracing + :security: YES + :safety: ASIL_B + :status: valid + :implements: logic_arc_int__tracing__tracing + +.. logic_arc_int:: Tracing + :id: logic_arc_int__tracing__tracing + :security: YES + :safety: ASIL_B + :status: valid + +.. logic_arc_int_op:: Trace + :id: logic_arc_int_op__tracing__trace + :security: YES + :safety: ASIL_B + :status: valid + :included_by: logic_arc_int__tracing__tracing diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index 44808adceb..b915c3ed6a 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -469,7 +469,7 @@ Functional Safety Management Feature Specific Work Products See feature tree documents (created by using :need:`PROCESS_gd_temp__feature_safety_wp`): -- Inter-process Communication: :doc:`/features/communication/ipc/safety_planning/index` +- Inter-process Communication: :ref:`safety_planning_ipc` - Common Libraries: - Logging: - Persistency: From 35903c85ec9ddacbd345a1a4eca91b02beccf28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20H=C3=A4ussler?= Date: Mon, 2 Jun 2025 08:53:18 +0200 Subject: [PATCH 015/102] process: templates for feature and module persistency added --- .../feature_name/architecture/index.rst | 155 ++++ docs/features/feature_name/index.rst | 192 ++++ .../feature_name/requirements/index.rst | 77 ++ .../feature_name/safety_analysis/dfa.rst | 868 ++++++++++++++++++ .../feature_name/safety_analysis/fmea.rst | 393 ++++++++ .../feature_name/safety_planning/index.rst | 130 +++ docs/index.rst | 1 + docs/modules/index.rst | 25 + docs/modules/persistency/docs/index.rst | 25 + .../modules/persistency/docs/manual/index.rst | 21 + .../persistency/docs/manual/safety_manual.rst | 89 ++ .../persistency/docs/release/release_note.rst | 90 ++ .../persistency/docs/safety_mgt/index.rst | 23 + .../safety_mgt/module_safety_package_fdr.rst | 73 ++ .../docs/safety_mgt/module_safety_plan.rst | 357 +++++++ .../safety_mgt/module_safety_plan_fdr.rst | 348 +++++++ .../module_verification_report.rst | 90 ++ .../json/docs/architecture/index.rst | 130 +++ .../json/docs/component_classification.rst | 181 ++++ docs/modules/persistency/json/docs/index.rst | 180 ++++ .../json/docs/requirements/index.rst | 72 ++ .../json/docs/safety_analysis/dfa.rst | 53 ++ .../json/docs/safety_analysis/fmea.rst | 53 ++ .../kvs/docs/architecture/index.rst | 130 +++ .../kvs/docs/component_classification.rst | 195 ++++ docs/modules/persistency/kvs/docs/index.rst | 180 ++++ .../kvs/docs/requirements/index.rst | 72 ++ .../kvs/docs/safety_analysis/dfa.rst | 53 ++ .../kvs/docs/safety_analysis/fmea.rst | 53 ++ 29 files changed, 4309 insertions(+) create mode 100644 docs/features/feature_name/architecture/index.rst create mode 100644 docs/features/feature_name/index.rst create mode 100644 docs/features/feature_name/requirements/index.rst create mode 100644 docs/features/feature_name/safety_analysis/dfa.rst create mode 100644 docs/features/feature_name/safety_analysis/fmea.rst create mode 100644 docs/features/feature_name/safety_planning/index.rst create mode 100644 docs/modules/index.rst create mode 100644 docs/modules/persistency/docs/index.rst create mode 100644 docs/modules/persistency/docs/manual/index.rst create mode 100644 docs/modules/persistency/docs/manual/safety_manual.rst create mode 100644 docs/modules/persistency/docs/release/release_note.rst create mode 100644 docs/modules/persistency/docs/safety_mgt/index.rst create mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst create mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst create mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst create mode 100644 docs/modules/persistency/docs/verification/module_verification_report.rst create mode 100644 docs/modules/persistency/json/docs/architecture/index.rst create mode 100644 docs/modules/persistency/json/docs/component_classification.rst create mode 100644 docs/modules/persistency/json/docs/index.rst create mode 100644 docs/modules/persistency/json/docs/requirements/index.rst create mode 100644 docs/modules/persistency/json/docs/safety_analysis/dfa.rst create mode 100644 docs/modules/persistency/json/docs/safety_analysis/fmea.rst create mode 100644 docs/modules/persistency/kvs/docs/architecture/index.rst create mode 100644 docs/modules/persistency/kvs/docs/component_classification.rst create mode 100644 docs/modules/persistency/kvs/docs/index.rst create mode 100644 docs/modules/persistency/kvs/docs/requirements/index.rst create mode 100644 docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst create mode 100644 docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst diff --git a/docs/features/feature_name/architecture/index.rst b/docs/features/feature_name/architecture/index.rst new file mode 100644 index 0000000000..ea48cde157 --- /dev/null +++ b/docs/features/feature_name/architecture/index.rst @@ -0,0 +1,155 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _feature_architecture_template: + +Feature Architecture +==================== + +.. document:: [Your Feature Name] Architecture + :id: doc__feature_name_architecture + :status: draft + :safety: ASIL_D + :realizes: wp__feature_arch + :tags: template + +.. attention:: + The above directive must be updated according to your Feature. + + - Modify ``Your Feature Name`` to be your Feature Name + - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Overview +-------- +Brief summary + +Description +----------- + +General Description + +Design Decisions + +Design Constraints + +Requirements +------------ + +.. code-block:: none + + .. needtable:: Overview of Feature Requirements + :style: table + :columns: title;id + :filter: search("feat_arch_sta__archdes$", "fulfils_back") + :colwidths: 70,30 + + +Rationale Behind Architecture Decomposition +******************************************* +mandatory: a motivation for the decomposition + +.. note:: Common decisions across features / cross cutting concepts is at the high level. + +Static Architecture +------------------- + +.. feat_arc_sta:: Static View + :id: feat_arc_sta__feature_name__static_view + :security: YES + :safety: ASIL_D + :status: invalid + :fulfils: feat_req__feature_name__some_title + :includes: logic_arc_int__feature_name__interface_name + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_feature(need(), needs) }} + +Dynamic Architecture +-------------------- + +.. feat_arc_dyn:: Dynamic View + :id: feat_arc_dyn__feature_name__dynamic_view + :security: YES + :safety: ASIL_D + :status: invalid + :fulfils: feat_req__feature_name__some_title + + put here a sequence diagram + +Logical Interfaces +------------------ + +.. logic_arc_int:: Interface Name + :id: logic_arc_int__feature_name__interface_name + :security: YES + :safety: ASIL_D + :status: invalid + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + +.. logic_arc_int_op:: Operation + :id: logic_arc_int_op__feature_name__operation + :security: YES + :safety: ASIL_D + :status: invalid + :included_by: logic_arc_int__feature_name__interface_name + +Module Viewpoint +---------------- + +The following modules are needed to be defined to be able to draw the static feature view. +They will be replaced by linking the proper module definitions in the used module's repositories as soon as those exist. + +.. mod_view_sta:: Module Name + :id: mod_view_sta__feature_name__module_name + :includes: comp_arc_sta__feature_name__component_name + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + +Used Components +--------------- + +The following components are needed to be defined to be able to draw the static feature view. +They will be replaced by linking the proper SW component definitions in the used module's repositories as soon as those exist. + +.. comp_arc_sta:: Component Name + :id: comp_arc_sta__feature_name__component_name + :safety: ASIL_D + :security: YES + :status: invalid + :implements: logic_arc_int__feature_name__interface_name + +.. note:: + Architecture can be split into multiple files, it is an High level architecture_design + which can be shown without actual c++/rust interfaces and data types + and there will be link to lower level architecture till code to get actual api descriptions. + +.. attention:: + The above directives must be updated according to your feature architecture. + + - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) + - Set the status to valid and start the review/merge process diff --git a/docs/features/feature_name/index.rst b/docs/features/feature_name/index.rst new file mode 100644 index 0000000000..61b16cda74 --- /dev/null +++ b/docs/features/feature_name/index.rst @@ -0,0 +1,192 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _feature_template: + +[Your Feature Name] +################### + +.. note:: Document header + +.. document:: [Your Feature Name] + :id: doc__feature_name + :status: draft + :safety: ASIL_D + :realizes: wp__feat_request + :tags: template + +.. attention:: + The above directive must be updated according to your Feature. + + - Modify ``document`` to be your Feature Name + - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_[your_feature_name]`` + + .. note:: + The feature flag must reflect the feature name in snake_case. Further, it is prepended with ``experimental_``, as + long as the feature is not yet stable. + +Abstract +======== + +[A short (~200 word) description of the contribution being addressed.] + + +Motivation +========== + +[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] + + .. note:: + The motivation is critical for CRs that want to change the existing features or infrastructure. + It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. + Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. + CRs submissions without sufficient motivation may be rejected. + + + +Rationale +========= + +[Describe why particular design decisions were made.] + + + .. note:: + The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. + + +Specification +============= + +[Describe the requirements, architecture of any new feature.] or +[Describe the change to requirements, architecture, implementation, process, documentation, infrastructure of any change request.] + + .. note:: + A CR shall specify the stakeholder requirements as part of our platform/project. + Thereby the :need:`rl__technical_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). + + + +Backwards Compatibility +======================= + +[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] + + +Security Impact +=============== + +[How could a malicious user take advantage of this new/modified feature?] + + .. note:: + If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which security requirements are affected or has to be changed? +Could the new/modified feature enable new threat scenarios? +Could the new/modified feature enable new attack paths? +Could the new/modified feature impact functional safety? +If applicable, which additional security measures must be implemented to mitigate the risk? + + .. note:: + Use Trust Boundary, Defense in Depth Analysis and/or Security Software Critically Analysis, + Vulnerability Analysis. + [Methods will be defined later in Process area Security Analysis] + These analyses may not be available at the time of creation of the feature (request) but content will be improved iteratively. + +Safety Impact +============= + +[How could the safety be impacted by the new/modified feature?] + + .. note:: + If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + Link here to the filled out :need:`Impact Analysis Template ` or copy the template in this chapter. + +Which safety requirements are affected or has to be changed? +Could the new/modified feature be a potential common cause or cascading failure initiator? +If applicable, which additional safety measures must be implemented to mitigate the risk? + + .. note:: + Use Dependency Failure Analysis and/or Safety Software Critically Analysis. + [Methods will be defined later in Process area Safety Analysis] + These analyses may not be available at the time of creation of the feature (request) but content will be improved iteratively. + +For new feature contributions: + +[What is the expected ASIL level?] + + +License Impact +============== + +[How could the copyright impacted by the license of the new contribution?] + + +How to Teach This +================= + +[How to teach users, new and experienced, how to apply the CR to their work.] + + .. note:: + For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. + + + +Rejected Ideas +============== + +[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] + + .. note:: + Throughout the discussion of a CR, various ideas will be proposed which are not accepted. + Those rejected ideas should be recorded along with the reasoning as to why they were rejected. + This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. + In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. + + + +Open Issues +=========== + +[Any points that are still being decided/discussed.] + + .. note:: + While a CR is in draft, ideas can come up which warrant further discussion. + Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. + This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. + + + +Footnotes +========= + +[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] + + +.. toctree:: + :hidden: + + requirements/index.rst + architecture/index.rst + safety_planning/index.rst + safety_analysis/fmea.rst + safety_analysis/dfa.rst diff --git a/docs/features/feature_name/requirements/index.rst b/docs/features/feature_name/requirements/index.rst new file mode 100644 index 0000000000..b5e6235f07 --- /dev/null +++ b/docs/features/feature_name/requirements/index.rst @@ -0,0 +1,77 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Requirements +############ + +.. document:: [Your Feature Name] Requirements + :id: doc__feature_name_requirements + :status: draft + :safety: ASIL_D + :realizes: wp__requirements__feat + :tags: template + +.. attention:: + The above directive must be updated according to your Feature. + + - Modify ``Your Feature Name`` to be your Feature Name + - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + + +=================================================================== + +.. stkh_req:: Template + :id: stkh_req__requirements__template + :reqtype: Non-Functional + :safety: ASIL_D + :rationale: Exists just for the template example + :status: invalid + + The platform shall ... + +.. attention:: + The above stakeholder requirement must be removed, it just serves as a link target for this template. + +.. feat_req:: Some Title + :id: feat_req__feature_name__some_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :satisfies: stkh_req__requirements__template + :status: invalid + + The Feature shall do xyz to the user to bring him to this condition at this time + + Note: (optional, not to be verified) + +.. aou_req:: Some Other Title + :id: aou_req__feature_name__some_other_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :status: invalid + + The Feature User shall do xyz to use the feature safely + +.. attention:: + The above directives must be updated according to your feature requirements. + + - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) + - Set the status to valid and start the review/merge process + - Add other needed requirements for your feature + +.. needextend:: "feature_name" in id + :+tags: feature_name diff --git a/docs/features/feature_name/safety_analysis/dfa.rst b/docs/features/feature_name/safety_analysis/dfa.rst new file mode 100644 index 0000000000..d3e9f3bda0 --- /dev/null +++ b/docs/features/feature_name/safety_analysis/dfa.rst @@ -0,0 +1,868 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Persistency DFA +############### + +.. document:: DFA + :id: doc__persistency_dfa + :status: draft + :safety: ASIL_B + :tags: feature_persistency + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_01 + | :violation_cause: Reused software module. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_02 + | :violation_cause: Libraries. . N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_04 + | :violation_cause: Basic software. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_05 + | :violation_cause: Operating system including scheduler. Platformebene. Nicht von Middleware handlebar + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_06 + | :violation_cause: Any service stack, e.g. communication stack. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_07 + | :violation_cause: Configuration data. Return values might be falsified. + | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__kvs__integrity_check + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_09 + | :violation_cause: Execution time. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_10 + | :violation_cause: Allocated memory. Diskussion aktuell in Feature-Community. JSON kann das, sollte aber eigentlich nicht erlaubt sein + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_01 + | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) <- Checken ob das Fehlerbild überhaupt passt. 1. Satzteil nicht passen zu 2.> + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_02 + | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information. Fehlerhafte ausführung oder nichtverfügbarkeit vom feature + | :mitigation: < NONE|ID from Feature Requirement> feat_req__kvs__integrity_check + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_03 + | :violation_cause: Insertion / sequence of information wie CO_01_02 + | :mitigation: < NONE|ID from Feature Requirement> feat_req__kvs__integrity_check + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_04 + | :violation_cause: Corruption of information, inconsistent data wie CO_01_02 + | :mitigation: < NONE|ID from Feature Requirement> keine Erkennung + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_05 + | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_06 + | :violation_cause: Information from a sender received by only a subset of the receivers. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_07 + | :violation_cause: Blocking access to a communication channel N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_02 + | :violation_cause: Configuration data. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_03 + | :violation_cause: Constants, or variables, being global to the two software functions. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_04 + | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_05 + | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function. Unklar was das Fehlerbild ist + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_01 + | :violation_cause: Memory miss-allocation and leaks. Platformebene + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_02 + | :violation_cause: Read/Write access to memory allocated to another software element. Platformebene + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_03 + | :violation_cause: Stack/Buffer under-/overflow. Könnte passieren, ist aber unwahrscheinlich in RUST. Recursive Funktionen könnten die Ursache sein. + | :mitigation: < NONE|ID from Feature Requirement> Compilerüberwachung / AoU + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_04 + | :violation_cause: Deadlocks. Könnten auftreten. Würde von Applikation verursacht werden. KVS kann da nichts machen + | :mitigation: < NONE|ID from Feature Requirement> AoU + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_05 + | :violation_cause: Livelocks wie UI_01_04 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_06 + | :violation_cause: Blocking of execution. Feature is not available. + | :mitigation: < NONE|ID from Feature Requirement> AoU + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_07 + | :violation_cause: Incorrect allocation of execution time. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_08 + | :violation_cause: Incorrect execution flow N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_09 + | :violation_cause: Incorrect synchronization between software elements N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_10 + | :violation_cause: CPU time depletion N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_11 + | :violation_cause: Memory depletion N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_12 + | :violation_cause: Other HW unavailability N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_02 + | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_03 + | :violation_cause: Same personal + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_04 + | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__kvs__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_05 + | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + + + + + + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_01 + | :violation_cause: Reused software modules + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_02 + | :violation_cause: Libraries + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_04 + | :violation_cause: Basic software + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_05 + | :violation_cause: Operating system including scheduler + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_06 + | :violation_cause: Any service stack, e.g. communication stack + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_07 + | :violation_cause: Configuration data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_09 + | :violation_cause: Execution time + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SR_01_10 + | :violation_cause: Allocated memory + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_01 + | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_02 + | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_03 + | :violation_cause: Insertion / sequence of information + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_04 + | :violation_cause: Corruption of information, inconsistent data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_05 + | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_06 + | :violation_cause: Information from a sender received by only a subset of the receivers + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: CO_01_07 + | :violation_cause: Blocking access to a communication channel + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SI_01_02 + | :violation_cause: Configuration data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SI_01_03 + | :violation_cause: Constants, or variables, being global to the two software functions + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SI_01_04 + | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SI_01_05 + | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_01 + | :violation_cause: Memory miss-allocation and leaks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_02 + | :violation_cause: Read/Write access to memory allocated to another software element + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_03 + | :violation_cause: Stack/Buffer under-/overflow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_04 + | :violation_cause: Deadlocks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_05 + | :violation_cause: Livelocks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_06 + | :violation_cause: Blocking of execution + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_07 + | :violation_cause: Incorrect allocation of execution time + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_08 + | :violation_cause: Incorrect execution flow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_09 + | :violation_cause: Incorrect synchronization between software elements + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_10 + | :violation_cause: CPU time depletion + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_11 + | :violation_cause: Memory depletion + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: UI_01_12 + | :violation_cause: Other HW unavailability + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SC_01_02 + | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SC_01_03 + | :violation_cause: Same personal + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SC_01_04 + | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_dfa:: + | :verifies: + | :id: feat_saf_DFA____ + | :violation_id: SC_01_05 + | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: diff --git a/docs/features/feature_name/safety_analysis/fmea.rst b/docs/features/feature_name/safety_analysis/fmea.rst new file mode 100644 index 0000000000..ec2affc54f --- /dev/null +++ b/docs/features/feature_name/safety_analysis/fmea.rst @@ -0,0 +1,393 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Persistency Safety Analysis +########################### + +.. document:: Safety Analysis + :id: doc__persistency_safety_analysis + :status: draft + :safety: ASIL_B + :tags: feature_persistency + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_01 + | :failure_effect: Message is not received. User is not able to use the feature. Middleware cant be used.A + | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_02 + | :failure_effect: message received too late. User might not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_03 + | :failure_effect: message received too early. No impact / feature reacts only if triggered on the trigger. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_04 + | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost). N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_05 + | :failure_effect: message is corrupted. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_06 + | :failure_effect: message is not sent. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_07 + | :failure_effect: message is unintended sent. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: CO_01_01 + | :failure_effect: minimum constraint boundary is violated. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: CO_01_02 + | :failure_effect: maximum constraint boundary is violated. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_01 + | :failure_effect: Process calculates wrong result(s). Feature is not usable. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_02 + | :failure_effect: processing too slow. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_03 + | :failure_effect: processing too fast. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_04 + | :failure_effect: loss of execution. User is not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_05 + | :failure_effect: processing changes to arbitrary process. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__kvs__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_06 + | :failure_effect: processing is not complete (infinite loop). User is not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + + + + + + + + + + + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_01 + | :failure_effect: message is not received + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_02 + | :failure_effect: message received too late + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_03 + | :failure_effect: message received too early + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_04 + | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_05 + | :failure_effect: message is corrupted + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_06 + | :failure_effect: message is not sent + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: MF_01_07 + | :failure_effect: message is unintended sent + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: CO_01_01 + | :failure_effect: minimum constraint boundary is violated + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: CO_01_02 + | :failure_effect: maximum constraint boundary is violated + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_01 + | :failure_effect: Process calculates wrong result(s) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_02 + | :failure_effect: processing too slow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_03 + | :failure_effect: processing too fast + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_04 + | :failure_effect: loss of execution + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_05 + | :failure_effect: processing changes to arbitrary process + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: + + | .. feat_saf_fmea:: Persistency + | :verifies: + | :id: feat_saf_FMEA__persistency__ + | :failure_mode: EX_01_06 + | :failure_effect: processing is not complete (infinite loop) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: + | :mitigation_coverage: <0..100%> + | :sufficient: + | :argument: + | :status: \ No newline at end of file diff --git a/docs/features/feature_name/safety_planning/index.rst b/docs/features/feature_name/safety_planning/index.rst new file mode 100644 index 0000000000..c45fd37406 --- /dev/null +++ b/docs/features/feature_name/safety_planning/index.rst @@ -0,0 +1,130 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _feature_safety_wp_template: + +Feature Safety Planning +======================= + +.. list-table:: Feature Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - :need:`wp__feat_request` + - :need:`gd_temp__change__feature_request` + - :ndf:`copy('status', need_id='gd_temp__change__feature_request')` + - https://github.com/eclipse-score/score/issues/760 + - :need:`doc__feature_name` + - :ndf:`copy('status', need_id='doc__feature_name')` + + * - :need:`wp__requirements__feat` + - :need:`gd_temp__req__feat_req` + - :ndf:`copy('status', need_id='gd_temp__req__feat_req')` + - https://github.com/eclipse-score/score/issues/960 + - :doc:`../requirements/index` + - see below + + * - :need:`wp__requirements__feat_aou` + - :need:`gd_temp__req__aou_req` + - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` + - https://github.com/eclipse-score/score/issues/960 + - :doc:`../requirements/index` + - see below + + * - :need:`wp__feature_arch` + - :need:`gd_temp__arch__feature` + - :ndf:`copy('status', need_id='gd_temp__arch__feature')` + - https://github.com/eclipse-score/score/issues/1020 + - :doc:`../architecture/index` + - see below + + * - :need:`wp__feature_safety_analysis` + - + - + - https://github.com/eclipse-score/score/issues/965 + - :doc:`../safety_analysis/doc__persistency_safety_analysis` + - + + * - :need:`wp__feature_dfa` + - + - + - https://github.com/eclipse-score/score/issues/965 + - :doc:`../safety_analysis/doc__persistency_dfa` + - + + * - :need:`wp__requirements__inspect` + - :need:`gd_chklst__req__inspection` + - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__sw_arch_verification` + - :need:`gd_chklst__arch__inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__verification__feat_int_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - + - https://github.com/eclipse-score/score/issues/964 + - + +.. attention:: + The above table must be updated according to your feature safety planning. + + - Create and link the issues to plan the work products (according to :need:`gd_guidl__saf_plan_definitions`) + - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`gd_guidl__saf_package`) + +Feature Requirements Status +--------------------------- + +.. needtable:: + :style: table + :types: feat_req + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title + +Feature AoU Status +------------------ + +.. needtable:: + :style: table + :types: aou_req + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title + +Feature Architecture Status +--------------------------- + +.. needtable:: + :style: table + :types: feat_arc_sta; feat_arc_dyn + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title diff --git a/docs/index.rst b/docs/index.rst index ebaf238ed1..bf21ee074b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -132,6 +132,7 @@ Project structure and processes introduction/index requirements/index features/index + modules/index contribute/index Releases PMP diff --git a/docs/modules/index.rst b/docs/modules/index.rst new file mode 100644 index 0000000000..616910914d --- /dev/null +++ b/docs/modules/index.rst @@ -0,0 +1,25 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _modules_template: + +Module +====== + +.. toctree:: + :maxdepth: 1 + :glob: + + */docs/index + */*/docs/index diff --git a/docs/modules/persistency/docs/index.rst b/docs/modules/persistency/docs/index.rst new file mode 100644 index 0000000000..3fc9455078 --- /dev/null +++ b/docs/modules/persistency/docs/index.rst @@ -0,0 +1,25 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Module Documents Persistency +############################ + +.. toctree:: + :maxdepth: 1 + :glob: + + manual/index.rst + safety_mgt/index.rst + verification/module_verification_report.rst + release/release_note.rst diff --git a/docs/modules/persistency/docs/manual/index.rst b/docs/modules/persistency/docs/manual/index.rst new file mode 100644 index 0000000000..08ba1a6e1a --- /dev/null +++ b/docs/modules/persistency/docs/manual/index.rst @@ -0,0 +1,21 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Manuals +####### + +.. toctree:: + :titlesonly: + + safety_manual diff --git a/docs/modules/persistency/docs/manual/safety_manual.rst b/docs/modules/persistency/docs/manual/safety_manual.rst new file mode 100644 index 0000000000..70108acee3 --- /dev/null +++ b/docs/modules/persistency/docs/manual/safety_manual.rst @@ -0,0 +1,89 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Safety Manual Template +====================== + +.. document:: Persistency Safety Manual + :id: doc__persistency_safety_manual + :status: draft + :safety: ASIL_B + :tags: feature_persistency + +This document implements + +Introduction/Scope +------------------ +| This manual will cover the Feature Persistency. It's based on the components + +Assumed Platform Safety Requirements +------------------------------------ +| For the the following safety related stakeholder requirements are assumed to define the top level functionality (purpose) of the . I.e. from these all the feature and component requirements implemented are derived. +| + +Assumptions of Use +------------------ + +Assumptions on the Environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +| Generally the assumption of the S-CORE platform SEooC is that it is integrated in a safe system, i.e. the POSIX OS it runs on is qualified and also the HW related failures are taken into account by the system integrator, if not otherwise stated in the module's safety concept. +| + +List of AoUs expected from the environment the platform / module runs on: + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" in need["tags"]: + results.append(need) + +Assumptions on the User +^^^^^^^^^^^^^^^^^^^^^^^ +| As there is no assumption on which specific OS and HW is used, the integration testing of the stakeholder and feature requirements is expected to be performed by the user of the platform SEooC. Tests covering all stakeholder and feature requirements performed on a reference platform (tbd link to reference platform specification), reviewed and passed are included in the platform SEooC safety case. +| Additionally the components of the platform may have additional specific assumptions how they are used. These are part of every module documentation: . Assumptions from components to their users can be fulfilled in two ways: +| 1. There are assumption which need to be fulfilled by all SW components, e.g. "every user of an IPC mechanism needs to make sure that he provides correct data (including appropriate ASIL level)" - in this case the AoU is marked as "platform". +| 2. There are assumption which can be fulfilled by a safety mechanism realized by some other S-CORE platform component and are therefore not relevant for an user who uses the whole platform. But those are relevant if you chose to use the module SEooC stand-alone - in this case the AoU is marked as "module". An example would be the "JSON read" which requires "The user shall provide a string as input which is not corrupted due to HW or QM SW errors." - which is covered when using together with safe S-CORE platform persistency feature. + +List of AoUs on the user of the platform features or the module of this safety manual: + +.. needtable:: + :style: table + :columns: title;id;status + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["aou_req"]): + if need and "environment" not in need["tags"]: + results.append(need) + +Safety concept of the SEooC +--------------------------- +| + +Safety Anomalies +---------------- +| Anomalies (bugs in ASIL SW, detected by testing or by users, which could not be fixed) known before release are documented in the platform/module release notes . + +References +---------- +| +| diff --git a/docs/modules/persistency/docs/release/release_note.rst b/docs/modules/persistency/docs/release/release_note.rst new file mode 100644 index 0000000000..80682eb639 --- /dev/null +++ b/docs/modules/persistency/docs/release/release_note.rst @@ -0,0 +1,90 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Release Note +============ + +.. note:: Document header + +.. document:: [Your Module Name] Release Note + :id: doc__module_name_release_note + :status: draft + :safety: ASIL_D + :realizes: wp__module_sw_release_note + :tags: template + +.. attention:: + The above directive must be updated according to your Module. + + - Modify ``Your Module Name`` to be your Module Name + - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``release_note`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + + + +| Module Name: [Module Name] +| Release Tag: vX.Y.Z +| Release Commit Hash: a1b2c3d4e5f6g7h8i9j0 +| Release Date: YYYY-MM-DD +| +| Overview +| -------- +| +| This document provides an overview of the changes, improvements, and bug fixes included in the software module release version vX.Y.Z. +| +| New Features +| ------------ +| +| - **Feature 1**: Brief description of the new feature. +| - **Feature 2**: Brief description of the new feature. +| - **Feature 3**: Brief description of the new feature. +| +| Improvements +| ------------ +| +| - **Improvement 1**: Brief description of the improvement. +| - **Improvement 2**: Brief description of the improvement. +| - **Improvement 3**: Brief description of the improvement. +| +| Bug Fixes +| --------- +| +| - **Bug 1**: Brief description of the bug fix. +| - **Bug 2**: Brief description of the bug fix. +| - **Bug 3**: Brief description of the bug fix. +| +| Compatibility +| ------------- +| +| - **Dependencies**: List any dependencies and their versions. +| +| Known Issues +| ------------ +| +| - **Issue 1**: Brief description of the known issue. Justification regarding safety impact. +| - **Issue 2**: Brief description of the known issue. Justification regarding safety impact. +| - **Issue 3**: Brief description of the known issue. Justification regarding safety impact. +| +| Upgrade Instructions +| -------------------- +| +| 1. **Step 1**: Description of the first step. +| 2. **Step 2**: Description of the second step. +| 3. **Step 3**: Description of the third step. +| +| Contact Information +| ------------------- +| +| For any questions or support, please contact the *Project lead* or raise an issue/discussion. diff --git a/docs/modules/persistency/docs/safety_mgt/index.rst b/docs/modules/persistency/docs/safety_mgt/index.rst new file mode 100644 index 0000000000..04718ba355 --- /dev/null +++ b/docs/modules/persistency/docs/safety_mgt/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Safety Management +################# + +.. toctree:: + :titlesonly: + + module_safety_plan + module_safety_plan_fdr + module_safety_package_fdr diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst new file mode 100644 index 0000000000..f841547bb8 --- /dev/null +++ b/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst @@ -0,0 +1,73 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Safety Package Formal Review Report +=================================== + +.. note:: Document header + +.. document:: [Your Module Name] Safety Package Formal Review + :id: doc__module_name_safety_package_fdr + :status: draft + :safety: ASIL_D + :realizes: wp__fdr_reports + :tags: template + +.. attention:: + The above directive must be updated according to your Module. + + - Modify ``Your Module Name`` to be your Module Name + - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``safety_package_fdr`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + + +**1. Purpose** + +The purpose of this review checklist is to report status of the formal review for the safety package. + +**2. Checklist** + +.. list-table:: Safety Package Checklist + :header-rows: 1 + + * - Id + - Safety package activity + - Compliant to ISO 26262? + - Comment + + * - 1 + - Is a safety package provided which matches the safety plan (i.e. all planned workproducts referenced)? + - [YES | NO ] + - + + * - 2 + - Is the argument how functional safety is achieved, provided in the safety package, plausible and sufficient? + - NO + - The argument is intentionally not provided by S-CORE. + + * - 3 + - Are the referenced work products available? + - [YES | NO ] + - + + * - 4 + - Are the referenced work products in released state, including the process safety audit? + - [YES | NO ] + - + + * - 5 + - If safety related deviations from the process or safety concept are documented, are these argued understandably? + - [YES | NO ] + - diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst new file mode 100644 index 0000000000..c07e3fe5dc --- /dev/null +++ b/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst @@ -0,0 +1,357 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Module Safety Plan +****************** + +.. note:: Document header + +.. document:: [Your Module Name] Safety Plan + :id: doc__module_name_safety_plan + :status: draft + :safety: ASIL_D + :realizes: wp__module_safety_plan + :tags: template + +.. attention:: + The above directive must be updated according to your Module. + + - Modify ``Your Module Name`` to be your Module Name + - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``safety_plan`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + + +Functional Safety Management Context +==================================== + +This Safety Plan adds to the :ref:`process_safety_management` all the module development relevant workproducts needed for ISO 26262 conformity. + +Functional Safety Management Scope +================================== + +This Safety Plan's scope is a SW module of the SW platform /index.rst>. +The module consists of one or more SW components and will be qualified as a SEooC. + +Functional Safety Management Roles +================================== + ++---------------------------+--------------------------------------------------------+ +| Safety Manager | | ++---------------------------+--------------------------------------------------------+ +| Project Manager | | ++---------------------------+--------------------------------------------------------+ + +Tailoring +========= + +Additional to the tailoring in the SW platform project as defined in the :ref:`process_safety_management` we define here the additional tailoring on module level. + +- Excluded for this module are additionally the following workproducts (and their related requirements): + - : - + +Functional Safety Module Workproducts +===================================== + +One set of workproducts for the module and one set for each component of the module: + +Module Workproducts List +------------------------ + +.. list-table:: Module Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - :need:`wp__module_safety_plan` + - :need:`gd_guidl__saf_plan_definitions` + - :ndf:`copy('status', need_id='gd_guidl__saf_plan_definitions')` + - + - this document + - see above + + * - :need:`wp__module_safety_package` + - :need:`gd_guidl__saf_package` + - :ndf:`copy('status', need_id='gd_guidl__saf_package')` + - + - this document (including the linked documentation) + - see above (and below) + + * - :need:`wp__fdr_reports` (module Safety Plan) + - :need:`gd_chklst__safety_plan` + - :ndf:`copy('status', need_id='gd_chklst__safety_plan')` + - + - :need:`doc__module_name_safety_plan_fdr` + - :ndf:`copy('status', need_id='doc__module_name_safety_plan_fdr')` + + * - :need:`wp__fdr_reports` (module Safety Package) + - :need:`gd_chklst__safety_package` + - :ndf:`copy('status', need_id='gd_chklst__safety_package')` + - + - :need:`doc__module_name_safety_package_fdr` + - :ndf:`copy('status', need_id='doc__module_name_safety_package_fdr')` + + * - :need:`wp__fdr_reports` (module's Safety Analyses & DFA) + - Safety Analysis FDR tbd + - + - + - + - + + * - :need:`wp__audit_report` + - performed by external experts + - n/a + - + - + - + + * - :need:`wp__module_sw_build_config` + - :need:`SCORE_doc__software_development_plan` + - :ndf:`copy('status', need_id='SCORE_doc__software_development_plan')` + - + - + - + + * - :need:`wp__module_safety_manual` + - :need:`gd_temp__safety_manual` + - :ndf:`copy('status', need_id='gd_temp__safety_manual')` + - + - :need:`doc__module_name_safety_manual` + - :ndf:`copy('status', need_id='doc__module_name_safety_manual')` + + * - :need:`wp__verification__module_ver_report` + - :need:`gd_temp__mod_ver_report` + - :ndf:`copy('status', need_id='gd_temp__mod_ver_report')` + - + - :need:`doc__module_name_verification_report` + - :ndf:`copy('status', need_id='doc__module_name_verification_report')` + + * - :need:`wp__module_sw_release_note` + - :need:`gd_temp__rel__mod_rel_note` + - :ndf:`copy('status', need_id='gd_temp__rel__mod_rel_note')` + - + - :need:`doc__module_name_release_note` + - :ndf:`copy('status', need_id='doc__module_name_release_note')` + +Component Workproducts List +---------------------------------- + +.. list-table:: Component Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP/doc status + + * - :need:`wp__requirements__comp` + - :need:`gd_temp__req__comp_req` + - :ndf:`copy('status', need_id='gd_temp__req__comp_req')` + - + - :need:`doc__component_name_requirements` + - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below + + * - :need:`wp__requirements__comp_aou` + - :need:`gd_temp__req__aou_req` + - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` + - + - :need:`doc__component_name_requirements` + - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below + + * - :need:`wp__hsi` + - + - + - + - + - + + * - :need:`wp__requirements__inspect` + - :need:`gd_chklst__req__inspection` + - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__component_arch` + - :need:`gd_temp__arch__comp` + - :ndf:`copy('status', need_id='gd_temp__arch__comp')` + - + - :need:`doc__component_name_architecture` + - doc :ndf:`copy('status', need_id='doc__component_name_architecture')` & WP below + + * - :need:`wp__sw_arch_verification` + - :need:`gd_chklst__arch__inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__sw_component_safety_analysis` + - + - + - + - :need:`doc__component_name_fmea` + - doc :ndf:`copy('status', need_id='doc__component_name_fmea')` & WP below + + * - :need:`wp__sw_component_dfa` + - + - + - + - :need:`doc__component_name_dfa` + - doc :ndf:`copy('status', need_id='doc__component_name_dfa')` & WP below + + * - :need:`wp__sw_implementation` + - :need:`gd_guidl__implementation` + - :ndf:`copy('status', need_id='gd_guidl__implementation')` + - + - + - + + * - :need:`wp__verification__sw_unit_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - + - + - + + * - :need:`wp__sw_implementation_inspection` + - :need:`gd_chklst__impl_inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__impl_inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__verification__comp_int_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - + - + - + + * - :need:`wp__sw_component_class` + - :need:`gd_guidl__component_classification` + - :ndf:`copy('status', need_id='gd_guidl__component_classification')` + - + - :need:`doc__component_name_comp_class` + - :ndf:`copy('status', need_id='doc__component_name_comp_class')` + +Note: In case the component is a new development, :need:`wp__sw_component_class` shall be removed from the above list (and also from the folders). +In case an OSS element is used in the module, part 6 has to be filled out. + +OSS (sub-)component qualification plan +====================================== + +For the selected OSS component the following workproducts will be implemented (and why): + +If the OSS element is classified as a + - component, then the below table shall match the above, adding the reasoning for tailoring of work products according to the OSS component classification. + - lower level component, then no workproducts additional to the component’s will be planned and activities below are part of the component’s issues. + +.. list-table:: OSS (sub-)component Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to issue + - Reasoning for tailoring + + * - :need:`wp__requirements__comp` + - + - Always needed (for Q and QR classification) and also improves process Id 2 + + * - :need:`wp__requirements__comp_aou` + - + - Always needed (for Q and QR classification) and also improves process Id 5 + + * - :need:`wp__hsi` + - n/a + - OSS needing special HW is an extreme exception. + + * - :need:`wp__requirements__inspect` + - n/a + - Checklist used in Pull Request Review + + * - :need:`wf__cr_mt_comparch` + - + - + + * - :need:`wp__sw_component_safety_analysis` + - + - + + * - :need:`wp__sw_arch_verification` + - + - + + * - :need:`wp__sw_implementation` + - n/a + - If source code is modified, this is not a OSS qualification any more. + + * - :need:`wp__verification__sw_unit_test` + - + - + + * - :need:`wp__sw_implementation_inspection` + - + - + + * - :need:`wp__verification__comp_int_test` + - + - Always needed (for Q and QR classification) + + * - :need:`wp__sw_component_class` + - + - Always needed as basis for tailoring. + +Work Product Status (for Safety Package) +======================================== + +Component Requirements Status +----------------------------- + +.. needtable:: + :style: table + :types: comp_req + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title + +Component AoU Status +-------------------- + +.. needtable:: + :style: table + :types: aou_req + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title + +Component Architecture Status +----------------------------- + +.. needtable:: + :style: table + :types: comp_arc_sta; comp_arc_dyn + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst new file mode 100644 index 0000000000..2ec526b291 --- /dev/null +++ b/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst @@ -0,0 +1,348 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Module Safety Plan +****************** + +.. note:: Document header + +.. document:: Persistency Safety Plan + :id: doc__persistency_safety_plan + :status: draft + :safety: ASIL_B + :realizes: wp__module_safety_plan + :tags: feature_persistency + +Functional Safety Management Context +==================================== + +This Safety Plan adds to the :ref:`process_safety_management` all the module development relevant workproducts needed for ISO 26262 conformity. + +Functional Safety Management Scope +================================== + +This Safety Plan's scope is a SW module of the SW platform :doc:`../docs/features/persistency/index`. +The module consists of one or more SW components and will be qualified as a SEooC. + +Functional Safety Management Roles +================================== + ++---------------------------+-------------------------------------------------------------------------------------+ +| Safety Manager | Volker Häussler `Issue #963 `_ | ++---------------------------+-------------------------------------------------------------------------------------+ +| Project Manager | Lars Bauhofer `Issue #963 `_ | ++---------------------------+-------------------------------------------------------------------------------------+ + +Tailoring +========= + +Additional to the tailoring in the SW platform project as defined in the :ref:`process_safety_management` we define here the additional tailoring on module level. + +- Excluded for this module are additionally the following workproducts (and their related requirements): + - none + +Functional Safety Module Workproducts +===================================== + +One set of workproducts for the module and one set for each component of the module: + +Module Workproducts List +------------------------ + +.. list-table:: Module Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - :need:`wp__module_safety_plan` + - :need:`gd_guidl__saf_plan_definitions` + - :ndf:`copy('status', need_id='gd_guidl__saf_plan_definitions')` + - `Issue #963 `_ + - this document + - see above + + * - :need:`wp__module_safety_package` + - :need:`gd_guidl__saf_package` + - :ndf:`copy('status', need_id='gd_guidl__saf_package')` + - `Issue #963 `_ + - this document (including the linked documentation) + - see above (and below) + + * - :need:`wp__fdr_reports` (module Safety Plan) + - :need:`gd_chklst__safety_plan` + - :ndf:`copy('status', need_id='gd_chklst__safety_plan')` + - `Issue #963 `_ + - :need:`doc__module_name_safety_plan_fdr` + - :ndf:`copy('status', need_id='doc__module_name_safety_plan_fdr')` + + * - :need:`wp__fdr_reports` (module Safety Package) + - :need:`gd_chklst__safety_package` + - :ndf:`copy('status', need_id='gd_chklst__safety_package')` + - `Issue #963 `_ + - :need:`doc__module_name_safety_package_fdr` + - :ndf:`copy('status', need_id='doc__module_name_safety_package_fdr')` + + * - :need:`wp__fdr_reports` (module's Safety Analyses & DFA) + - Safety Analysis FDR tbd + - + - `Issue #965 `_ + - + - + + * - :need:`wp__audit_report` + - performed by external experts + - n/a + - + - + - + + * - :need:`wp__module_sw_build_config` + - :need:`SCORE_doc__software_development_plan` + - :ndf:`copy('status', need_id='SCORE_doc__software_development_plan')` + - + - + - + + * - :need:`wp__module_safety_manual` + - :need:`gd_temp__safety_manual` + - :ndf:`copy('status', need_id='gd_temp__safety_manual')` + - + - :need:`doc__module_name_safety_manual` + - :ndf:`copy('status', need_id='doc__module_name_safety_manual')` + + * - :need:`wp__verification__module_ver_report` + - :need:`gd_temp__mod_ver_report` + - :ndf:`copy('status', need_id='gd_temp__mod_ver_report')` + - + - :need:`doc__module_name_verification_report` + - :ndf:`copy('status', need_id='doc__module_name_verification_report')` + + * - :need:`wp__module_sw_release_note` + - :need:`gd_temp__rel__mod_rel_note` + - :ndf:`copy('status', need_id='gd_temp__rel__mod_rel_note')` + - + - :need:`doc__module_name_release_note` + - :ndf:`copy('status', need_id='doc__module_name_release_note')` + +Component Workproducts List +---------------------------------- + +.. list-table:: Component Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP/doc status + + * - :need:`wp__requirements__comp` + - :need:`gd_temp__req__comp_req` + - :ndf:`copy('status', need_id='gd_temp__req__comp_req')` + - + - :need:`doc__component_name_requirements` + - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below + + * - :need:`wp__requirements__comp_aou` + - :need:`gd_temp__req__aou_req` + - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` + - + - :need:`doc__component_name_requirements` + - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below + + * - :need:`wp__hsi` + - + - + - + - + - + + * - :need:`wp__requirements__inspect` + - :need:`gd_chklst__req__inspection` + - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__component_arch` + - :need:`gd_temp__arch__comp` + - :ndf:`copy('status', need_id='gd_temp__arch__comp')` + - + - :need:`doc__component_name_architecture` + - doc :ndf:`copy('status', need_id='doc__component_name_architecture')` & WP below + + * - :need:`wp__sw_arch_verification` + - :need:`gd_chklst__arch__inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__sw_component_safety_analysis` + - + - + - + - :need:`doc__component_name_fmea` + - doc :ndf:`copy('status', need_id='doc__component_name_fmea')` & WP below + + * - :need:`wp__sw_component_dfa` + - + - + - + - :need:`doc__component_name_dfa` + - doc :ndf:`copy('status', need_id='doc__component_name_dfa')` & WP below + + * - :need:`wp__sw_implementation` + - :need:`gd_guidl__implementation` + - :ndf:`copy('status', need_id='gd_guidl__implementation')` + - + - + - + + * - :need:`wp__verification__sw_unit_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - + - + - + + * - :need:`wp__sw_implementation_inspection` + - :need:`gd_chklst__impl_inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__impl_inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__verification__comp_int_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - + - + - + + * - :need:`wp__sw_component_class` + - :need:`gd_guidl__component_classification` + - :ndf:`copy('status', need_id='gd_guidl__component_classification')` + - + - :need:`doc__component_name_comp_class` + - :ndf:`copy('status', need_id='doc__component_name_comp_class')` + +Note: In case the component is a new development, :need:`wp__sw_component_class` shall be removed from the above list (and also from the folders). +In case an OSS element is used in the module, part 6 has to be filled out. + +OSS (sub-)component qualification plan +====================================== + +For the selected OSS component the following workproducts will be implemented (and why): + +If the OSS element is classified as a + - component, then the below table shall match the above, adding the reasoning for tailoring of work products according to the OSS component classification. + - lower level component, then no workproducts additional to the component’s will be planned and activities below are part of the component’s issues. + +.. list-table:: OSS (sub-)component Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to issue + - Reasoning for tailoring + + * - :need:`wp__requirements__comp` + - + - Always needed (for Q and QR classification) and also improves process Id 2 + + * - :need:`wp__requirements__comp_aou` + - + - Always needed (for Q and QR classification) and also improves process Id 5 + + * - :need:`wp__hsi` + - n/a + - OSS needing special HW is an extreme exception. + + * - :need:`wp__requirements__inspect` + - n/a + - Checklist used in Pull Request Review + + * - :need:`wf__cr_mt_comparch` + - + - + + * - :need:`wp__sw_component_safety_analysis` + - + - + + * - :need:`wp__sw_arch_verification` + - + - + + * - :need:`wp__sw_implementation` + - n/a + - If source code is modified, this is not a OSS qualification any more. + + * - :need:`wp__verification__sw_unit_test` + - + - + + * - :need:`wp__sw_implementation_inspection` + - + - + + * - :need:`wp__verification__comp_int_test` + - + - Always needed (for Q and QR classification) + + * - :need:`wp__sw_component_class` + - + - Always needed as basis for tailoring. + +Work Product Status (for Safety Package) +======================================== + +Component Requirements Status +----------------------------- + +.. needtable:: + :style: table + :types: comp_req + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title + +Component AoU Status +-------------------- + +.. needtable:: + :style: table + :types: aou_req + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title + +Component Architecture Status +----------------------------- + +.. needtable:: + :style: table + :types: comp_arc_sta; comp_arc_dyn + :tags: component_name + :columns: id;status;tags + :colwidths: 25,25,25 + :sort: title diff --git a/docs/modules/persistency/docs/verification/module_verification_report.rst b/docs/modules/persistency/docs/verification/module_verification_report.rst new file mode 100644 index 0000000000..5e4169687b --- /dev/null +++ b/docs/modules/persistency/docs/verification/module_verification_report.rst @@ -0,0 +1,90 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Verification Report +=================== + +.. note:: Document header + +.. document:: [Your Module Name] Verification Report + :id: doc__module_name_verification_report + :status: draft + :safety: ASIL_D + :realizes: wp__verification__module_ver_report + :tags: template + +.. attention:: + The above directive must be updated according to your Module. + + - Modify ``Your Module Name`` to be your Module Name + - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``verification_report`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + + +This verification report is based on the :need:`SCORE_doc__verification_plan`. +It covers all the components of the above stated module. + +Verification Report contains: + +**1. Verification Coverage** + +**1.1. on Requirements** + - Lists of component requirements (incl. AoU satisfied by the component) tested by which test case, passed/failed and completeness verdict + (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) + - For external component Assumptions of Use: coverage by platform safety manual or feature/components incl. test case, passed/failed and completeness verdict + - This is split in a list of QM requirements tested and a separate list of tests for ASIL rated requirements. + - List of component requirements (ASIL rated) linked to inspection checklist and verdict (derived from PR export) + +**1.2. on Architecture** + - List of component architecture tags tested by which test case, passed/failed and completeness verdict + (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) + - This is split in a list of QM components tested and a separate list of tests for ASIL rated components. + - List of component architecture tags (ASIL rated) linked to inspection checklist and verdict (derived from PR export) + +**1.3. on Detailed Design** + - List of detailed design tags tested by which test case, passed/failed and completeness verdict + (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) + - This is split in a list of QM components tested and a separate list of tests for ASIL rated components. + - List of detailed design tags (ASIL rated) linked to inspection checklist and verdict (derived from PR export) + + - The lists may also contain other verification methods like "Analysis" - process tbd + +**2. DFA Report** + - List of the performed component DFA, pass/fail with open mitigations + +**3. Safety Analysis Report** + - List of the performed component Safety Analysis, pass/fail with open mitigations + +**4. Unit Verification Coverage** + +**4.1. Structural Coverage** + - List of the units with C0(line) and C1(branch) coverage absolute and percentage + (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) + - List includes a column for the safety rating of each unit. + +**4.2. Static Code Analysis** + - List of the units with compiler warning numbers and coding rule violation numbers + (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) + - List includes a column for the safety rating of each unit. + +**4.3. Manual Code Inspection** + - List of components (ASIL rated) linked to inspection checklist and verdict (derived from PR export) + +**5. Software component qualification verification report** + - Contains the needed verification results if for some components a qualification of pre-developed SW is performed. + +**Note1:** The verification report is valid for the module version tagged together with the report + +**Note2:** All the above lists are generated automatically diff --git a/docs/modules/persistency/json/docs/architecture/index.rst b/docs/modules/persistency/json/docs/architecture/index.rst new file mode 100644 index 0000000000..731769dd5b --- /dev/null +++ b/docs/modules/persistency/json/docs/architecture/index.rst @@ -0,0 +1,130 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _component_architecture_template: + +Component Architecture +====================== + +.. document:: [Your Component Name] Architecture + :id: doc__component_name_architecture + :status: draft + :safety: ASIL_D + :realizes: wp__component_arch + :tags: template + +.. attention:: + The above directive must be updated according to your needs. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Overview +-------- +Brief summary + +Requirements Linked to Component Architecture +--------------------------------------------- + +.. code-block:: none + + .. needtable:: Overview of Component Requirements + :style: table + :columns: title;id + :filter: search("comp_arch_sta__archdes$", "fulfils_back") + :colwidths: 70,30 + +Description +----------- + +General Description + +Design Decisions + +Design Constraints + +Rationale Behind Architecture Decomposition +******************************************* +mandatory: a motivation for the decomposition or reason for not further splitting it into sub components. + +.. note:: Common decisions across components / cross cutting concepts is at the higher level. + +Static Architecture +------------------- + +The components are designed to cover the expectations from the feature architecture +(i.e. if already exists a definition it should be taken over and enriched). + +.. comp_arc_sta:: Component Name (Static View) + :id: comp_arc_sta__component_name__static_view + :security: YES + :safety: ASIL_D + :status: invalid + :implements: logic_arc_int__feature_name__interface_name + :fulfils: comp_req__component_name__some_title + :includes: comp_arc_sta__component_name__2 + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +Dynamic Architecture +-------------------- + +.. comp_arc_dyn:: Dynamic View + :id: comp_arc_dyn__component_name__dynamic_view + :security: YES + :safety: ASIL_D + :status: invalid + :fulfils: comp_req__component_name__some_title + + put here a sequence diagram + + +Interfaces +---------- + +.. code-block:: rst + + .. real_arc_int:: + :id: real_arc_int__<component>__<Title> + :security: <YES|NO> + :safety: <QM|ASIL_B|ASIL_D> + :fulfils: <link to component requirement id> + :language: cpp + +Lower Level Components +---------------------- + +.. comp_arc_sta:: Component Name 2 + :id: comp_arc_sta__component_name__2 + :status: invalid + :safety: ASIL_D + :security: YES + :implements: logic_arc_int__feature_name__interface_name + + no architecture but detailed design + +.. note:: + Architecture can be split into multiple files. At component level the public interfaces to be used by the user and tester to be shown. + +.. attention:: + The above directives must be updated according to your component architecture. + + - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) + - Set the status to valid and start the review/merge process diff --git a/docs/modules/persistency/json/docs/component_classification.rst b/docs/modules/persistency/json/docs/component_classification.rst new file mode 100644 index 0000000000..68d3a5d262 --- /dev/null +++ b/docs/modules/persistency/json/docs/component_classification.rst @@ -0,0 +1,181 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Component Classification +======================== + +.. document:: Persistency Component Classification + :id: doc__persistency_component_classification + :status: draft + :safety: ASIL_B + :realizes: wp__sw_component_class + :tags: feature_persistency + +| Classification of tiny json +| +| `tiny jason <https://github.com/rhysd/tinyjson>`_ V.2.5.1 +| +| Additional documentation considered: +| `Documentation for tiny jason <https://docs.rs/tinyjson/latest/tinyjson/>`_ + + +Step 1: Determine (P): the uncertainty of the Processes applied +--------------------------------------------------------------- + +| Apply the process measures to determine (P). +| The result of a process measure shall have as outcome [HE, PE, NE] +| - HE: High Evidence +| - PE: Partly Evidence but Manageable +| - NE: No Evidence + +.. list-table:: Determine (P) + :header-rows: 1 + + * - Id + - Indicator for applying process + - Result + - Rationale for result + + * - 1 + - Are rules, state-of-the art processes applied for the design, implementation and verification? + - PE + - Rules for Safe Rust applied. + + * - 2 + - Are requirements available? + - PE + - n/a. Tinyjson is a library to parse/generate JSON format document. So this is the main requirement. + + * - 3 + - Are specifications for functionalities and properties available (architecture)? + - PE + - Yes in the documentation of tinyjson. + + * - 4 + - Are design specifications available? + - PE + - n/a + + * - 5 + - Are configuration specification and data available, if applicable? + - PE + - Yes in the documentation of tinyjson. + + * - 6 + - Are verification measures including tests and reports available? + - HE + - Stored in github repo within folder tests. + + +| (P=1) shall be selected when none of the determined process measures indicate PE or NE. +| (P=2) shall be selected when at least one of the determined process measures indicate PE or NE, but the gaps evaluated are acceptable, means +| the risk of systematic faults due to these gaps is sufficiently low or manageable by mitigating the gaps. +| (P=3) in all other cases. + +Tinyjson determined as P=2. + + +Step 2: Determine (C): the uncertainty of finding systematic faults based on the Complexity +------------------------------------------------------------------------------------------- + +| Apply the complexity measures to determine (C). +| The result of a complexity measure shall have as outcome [NH, HM, NM] +| - NH: Not High +| - HM: High but Manageable +| - NM: high and Not Manageable +| +| **Complexity measure for programming language: <C++ or RUST>** + +.. list-table:: Determine (C) for RUST + :header-rows: 1 + + * - Id + - Indicator for high Complexity + - Complexity measure Tool + - Result + - Number + + * - 1 + - High amount of Lines of Code + - Lines of Code (without comments) (generated code is excluded, e.g. ProtoCmpl) + - NH + - 2367 loc + + * - 2 + - Unsafe code used / total unsafe code + - Count: + * LoUC+N: lines of unsafe code with safety note + * LoUC : lines of unsafe code, no safety note + - NH. Tinyjson is written in Safe Rust. + - 0 + + * - 3 + - | Test exists / Coverage (Function, Line) + | (maybe better: testability, but how to measure?) + - Existing Tests Coverage + - NH + - <Number> + + * - 4 + - High amount of public function interfaces + - Number of public function interfaces + - NH + - <Number> + + * - 5 + - High amount of function parameters + - Number of parameters + - NH + - <Number> + + +| (C=1) shall be selected when none of the determined complexity measures indicate HM or NM. +| (C=2) shall be selected when at least one of the determined complexity measures indicate HM or NM, but the gaps evaluated are acceptable, means +| the risk of systematic faults due to these gaps is sufficiently low in the context of S-CORE or manageable by mitigating the gaps. +| (C=3) in all other cases. +| + +Tinyjson is determined as C=1 + + +Step 3: Determine (CLAS_OUT): the classification outcome +-------------------------------------------------------- + +| Select CLAS_OUT depending on the determined values of (C) and (P) + ++-------+-----------------------+ +| ( C ) | ( P ) | ++-------+-------+-------+-------+ +| | 1 | 2 | 3 | ++=======+=======+=======+=======+ +| 1 | Q | Q | QR | ++-------+-------+-------+-------+ +| 2 | QR | QR | QR | ++-------+-------+-------+-------+ +| 3 | QR | QR | NQ | ++-------+-------+-------+-------+ + +Tinyjson is classified as CLAS_OUT=Q + + +Step 4: Document all results and rationale for choosing (P) and (C) and (CLAS_OUT) +---------------------------------------------------------------------------------- +This document + + +Step 5: Based on (CLAS_OUT) select the activities +------------------------------------------------- + +| As soon as the contribution request containing this is in status "Accepted", the module safety plan for the component development is adapted based on the following: +| - Q: Follow the processes for qualification of software components in a safety context. diff --git a/docs/modules/persistency/json/docs/index.rst b/docs/modules/persistency/json/docs/index.rst new file mode 100644 index 0000000000..aef22a742b --- /dev/null +++ b/docs/modules/persistency/json/docs/index.rst @@ -0,0 +1,180 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _component_template: + +Tiny JSON +######### + +.. note:: Document header + +.. document:: [Your Component Name] + :id: doc__component_name + :status: draft + :safety: ASIL_D + :realizes: wp__cmpt_request + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``document`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Abstract +======== + +[A short (~200 word) description of the contribution being addressed.] + + +Motivation +========== + +[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] + + .. note:: + The motivation is critical for CRs that want to change the existing components. + It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. + Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. + CRs submissions without sufficient motivation may be rejected. + + + +Rationale +========= + +[Describe why particular design decisions were made.] + + + .. note:: + The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. + + +Specification +============= + +[Describe the requirements, architecture of any new component.] or +[Describe the change to requirements, architecture, implementation, documentation of any change request.] + + .. note:: + A CR shall specify the component requirements as part of our platform/project. + Thereby the :need:`rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). + + + +Backwards Compatibility +======================= + +[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] + + +Security Impact +=============== + +[How could a malicious user take advantage of this new/modified component?] + + .. note:: + If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which security requirements are affected or has to be changed? +Could the new/modified component enable new threat scenarios? +Could the new/modified component enable new attack paths? +Could the new/modified component impact functional safety? +If applicable, which additional security measures must be implemented to mitigate the risk? + + .. note:: + Use Security Software Critically Analysis, Vulnerability Analysis. + [Methods will be defined later in Process area Security Analysis] + + +Safety Impact +============= + +[How could the safety be impacted by the new/modified component?] + + .. note:: + If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which safety requirements are affected or has to be changed? +Could the new/modified component be a potential common cause or cascading failure initiator? +If applicable, which additional safety measures must be implemented to mitigate the risk? + + .. note:: + Use Dependency Failure Analysis and/or Safety Software Critically Analysis. + [Methods will be defined later in Process area Safety Analysis] + +For new feature/component contributions: + +[What is the expected ASIL level?] +[What is the expected classification of the contribution?] + + .. note:: + Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`gd_temp__component_classification`. + +License Impact +============== + +[How could the copyright impacted by the license of the new contribution?] + + +How to Teach This +================= + +[How to teach users, new and experienced, how to apply the CR to their work.] + + .. note:: + For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. + + + +Rejected Ideas +============== + +[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] + + .. note:: + Throughout the discussion of a CR, various ideas will be proposed which are not accepted. + Those rejected ideas should be recorded along with the reasoning as to why they were rejected. + This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. + In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. + + + +Open Issues +=========== + +[Any points that are still being decided/discussed.] + + .. note:: + While a CR is in draft, ideas can come up which warrant further discussion. + Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. + This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. + + + +Footnotes +========= + +[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] + +.. toctree:: + :hidden: + + requirements/index.rst + architecture/index.rst + safety_analysis/fmea.rst + safety_analysis/dfa.rst + component_classification.rst diff --git a/docs/modules/persistency/json/docs/requirements/index.rst b/docs/modules/persistency/json/docs/requirements/index.rst new file mode 100644 index 0000000000..9e0d6d7b6f --- /dev/null +++ b/docs/modules/persistency/json/docs/requirements/index.rst @@ -0,0 +1,72 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Requirements +############ + +.. document:: [Your Component Name] Requirements + :id: doc__component_name_requirements + :status: draft + :safety: ASIL_D + :realizes: wp__requirements__comp + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +<Headlines (for the list of requirements if structuring is needed)> +=================================================================== + +.. comp_req:: Some Title + :id: comp_req__component_name__some_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :satisfies: feat_req__feature_name__some_title + :status: invalid + + The Component shall do xyz to another component to bring it to this condition at this time + + Note: (optional, not to be verified) + +.. attention:: + The above directive must be updated according to your component requirements. + + - Replace the example content by the real content for your first requirement + - Set the status to valid and start the review/merge process + - Add other needed requirements for your component + +.. aou_req:: Next Title + :id: aou_req__component_name__next_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :status: invalid + + The Component User shall do xyz to use the component safely + +.. attention:: + The above directives must be updated according to your feature requirements. + + - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) + - Set the status to valid and start the review/merge process + - Add other needed requirements for your feature + +.. needextend:: "component_name" in id + :+tags: component_name diff --git a/docs/modules/persistency/json/docs/safety_analysis/dfa.rst b/docs/modules/persistency/json/docs/safety_analysis/dfa.rst new file mode 100644 index 0000000000..1626d6304c --- /dev/null +++ b/docs/modules/persistency/json/docs/safety_analysis/dfa.rst @@ -0,0 +1,53 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Dependent Failure Analysis +========================== + +.. document:: [Your Component Name] DFA + :id: doc__component_name_dfa + :status: draft + :safety: ASIL_D + :realizes: wp__sw_component_dfa + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_dfa`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Dependent Failure Intitiators +----------------------------- + +.. code-block:: rst + + .. comp_saf_dfa:: <Element descriptor> + :id: comp_saf_DFA__<Component>__<Element descriptor> + :violation_id: <ID from Dependent Failure Initiators list :need:`gd_guidl__dfi`> + :violation_effect: <Effect caused by the initiator (leading to a violation of a safety goal)> + :verifies: <ID from Component Architecture> + :mitigated_by: < NONE|ID from Component Requirement> + :sufficient: <yes|no> + :argument: <text to argument why measure is sufficient> + :status: <valid|invalid> + +.. attention:: + The above directive must be updated according to your component DFA. + + - Remove the ``code-block`` + - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/json/docs/safety_analysis/fmea.rst b/docs/modules/persistency/json/docs/safety_analysis/fmea.rst new file mode 100644 index 0000000000..319c63d4ef --- /dev/null +++ b/docs/modules/persistency/json/docs/safety_analysis/fmea.rst @@ -0,0 +1,53 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Safety Analysis : FMEA +====================== + +.. document:: [Your Component Name] FMEA + :id: doc__component_name_fmea + :status: draft + :safety: ASIL_D + :realizes: wp__sw_component_safety_analysis + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_fmea`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Failure Mode List +----------------- + +.. code-block:: rst + + .. comp_saf_fmea:: <Element descriptor> + :id: comp_saf_FMEA__<Component>__<Element descriptor> + :failure_mode: <ID from fault model :need:`gd_guidl__fault_models`> + :failure_effect: <Effect caused by the failure (leading to a violation of a safety goal)> + :verifies: <ID from Component Architecture> + :mitigated_by: < NONE|ID from Component Requirement> + :sufficient: <yes|no> + :argument: <text to argument why measure is sufficient> + :status: <valid|invalid> + +.. attention:: + The above directive must be updated according to your component FMEA. + + - Remove the ``code-block`` + - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/kvs/docs/architecture/index.rst b/docs/modules/persistency/kvs/docs/architecture/index.rst new file mode 100644 index 0000000000..731769dd5b --- /dev/null +++ b/docs/modules/persistency/kvs/docs/architecture/index.rst @@ -0,0 +1,130 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _component_architecture_template: + +Component Architecture +====================== + +.. document:: [Your Component Name] Architecture + :id: doc__component_name_architecture + :status: draft + :safety: ASIL_D + :realizes: wp__component_arch + :tags: template + +.. attention:: + The above directive must be updated according to your needs. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Overview +-------- +Brief summary + +Requirements Linked to Component Architecture +--------------------------------------------- + +.. code-block:: none + + .. needtable:: Overview of Component Requirements + :style: table + :columns: title;id + :filter: search("comp_arch_sta__archdes$", "fulfils_back") + :colwidths: 70,30 + +Description +----------- + +General Description + +Design Decisions + +Design Constraints + +Rationale Behind Architecture Decomposition +******************************************* +mandatory: a motivation for the decomposition or reason for not further splitting it into sub components. + +.. note:: Common decisions across components / cross cutting concepts is at the higher level. + +Static Architecture +------------------- + +The components are designed to cover the expectations from the feature architecture +(i.e. if already exists a definition it should be taken over and enriched). + +.. comp_arc_sta:: Component Name (Static View) + :id: comp_arc_sta__component_name__static_view + :security: YES + :safety: ASIL_D + :status: invalid + :implements: logic_arc_int__feature_name__interface_name + :fulfils: comp_req__component_name__some_title + :includes: comp_arc_sta__component_name__2 + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + +Dynamic Architecture +-------------------- + +.. comp_arc_dyn:: Dynamic View + :id: comp_arc_dyn__component_name__dynamic_view + :security: YES + :safety: ASIL_D + :status: invalid + :fulfils: comp_req__component_name__some_title + + put here a sequence diagram + + +Interfaces +---------- + +.. code-block:: rst + + .. real_arc_int:: <Title> + :id: real_arc_int__<component>__<Title> + :security: <YES|NO> + :safety: <QM|ASIL_B|ASIL_D> + :fulfils: <link to component requirement id> + :language: cpp + +Lower Level Components +---------------------- + +.. comp_arc_sta:: Component Name 2 + :id: comp_arc_sta__component_name__2 + :status: invalid + :safety: ASIL_D + :security: YES + :implements: logic_arc_int__feature_name__interface_name + + no architecture but detailed design + +.. note:: + Architecture can be split into multiple files. At component level the public interfaces to be used by the user and tester to be shown. + +.. attention:: + The above directives must be updated according to your component architecture. + + - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) + - Set the status to valid and start the review/merge process diff --git a/docs/modules/persistency/kvs/docs/component_classification.rst b/docs/modules/persistency/kvs/docs/component_classification.rst new file mode 100644 index 0000000000..7a6214f3a3 --- /dev/null +++ b/docs/modules/persistency/kvs/docs/component_classification.rst @@ -0,0 +1,195 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Component Classification +======================== + +.. note:: Document header + +.. document:: [Your Component Name] Component Classification + :id: doc__component_name_comp_class + :status: draft + :safety: ASIL_D + :realizes: wp__sw_component_class + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +| Classification of <component> +| +| <Link to OSS component source (e.g. in github) including the selected version> +| +| Additional documentation considered: +| <list of documentation links> + + +Step 1: Determine (P): the uncertainty of the Processes applied +--------------------------------------------------------------- + +| Apply the process measures to determine (P). +| The result of a process measure shall have as outcome [HE, PE, NE] +| - HE: High Evidence +| - PE: Partly Evidence but Manageable +| - NE: No Evidence + +.. list-table:: Determine (P) + :header-rows: 1 + + * - Id + - Indicator for applying process + - Result + - Rationale for result + + * - 1 + - Are rules, state-of-the art processes applied for the design, implementation and verification? + - <HE|PE|NE> + - <Rationale for result> + + * - 2 + - Are requirements available? + - <HE|PE|NE> + - <Rationale for result> + + * - 3 + - Are specifications for functionalities and properties available (architecture)? + - <HE|PE|NE> + - <Rationale for result> + + * - 4 + - Are design specifications available? + - <HE|PE|NE> + - <Rationale for result> + + * - 5 + - Are configuration specification and data available, if applicable? + - <HE|PE|NE> + - <Rationale for result> + + * - 6 + - Are verification measures including tests and reports available? + - <HE|PE|NE> + - <Rationale for result> + + +| (P=1) shall be selected when none of the determined process measures indicate PE or NE. +| (P=2) shall be selected when at least one of the determined process measures indicate PE or NE, but the gaps evaluated are acceptable, means +| the risk of systematic faults due to these gaps is sufficiently low or manageable by mitigating the gaps. +| (P=3) in all other cases. + +<component name> is determined as P=<1|2|3> + + +Step 2: Determine (C): the uncertainty of finding systematic faults based on the Complexity +------------------------------------------------------------------------------------------- + +| Apply the complexity measures to determine (C). +| The result of a complexity measure shall have as outcome [NH, HM, NM] +| - NH: Not High +| - HM: High but Manageable +| - NM: high and Not Manageable +| +| **Complexity measure for programming language: <C++ or RUST>** + +<select the correct table below (table for C++ is TBD)> + +.. list-table:: Determine (C) for RUST + :header-rows: 1 + + * - Id + - Indicator for high Complexity + - Complexity measure Tool + - Result + - Number + + * - 1 + - High amount of Lines of Code + - Lines of Code (without comments) (generated code is excluded, e.g. ProtoCmpl) + - <NH|HM|NM> + - <Number> + + * - 2 + - Unsafe code used / total unsafe code + - Count: + * LoUC+N: lines of unsafe code with safety note + * LoUC : lines of unsafe code, no safety note + - <NH|HM|NM> + - <Number> + + * - 3 + - | Test exists / Coverage (Function, Line) + | (maybe better: testability, but how to measure?) + - Existing Tests Coverage + - <NH|HM|NM> + - <Number> + + * - 4 + - High amount of public function interfaces + - Number of public function interfaces + - <NH|HM|NM> + - <RNumber> + + * - 5 + - High amount of function parameters + - Number of parameters + - <NH|HM|NM> + - <Number> + + +| (C=1) shall be selected when none of the determined complexity measures indicate HM or NM. +| (C=2) shall be selected when at least one of the determined complexity measures indicate HM or NM, but the gaps evaluated are acceptable, means +| the risk of systematic faults due to these gaps is sufficiently low in the context of S-CORE or manageable by mitigating the gaps. +| (C=3) in all other cases. +| + +<component name> is determined as C=<1|2|3> + + +Step 3: Determine (CLAS_OUT): the classification outcome +-------------------------------------------------------- + +| Select CLAS_OUT depending on the determined values of (C) and (P) + ++-------+-----------------------+ +| ( C ) | ( P ) | ++-------+-------+-------+-------+ +| | 1 | 2 | 3 | ++=======+=======+=======+=======+ +| 1 | Q | Q | QR | ++-------+-------+-------+-------+ +| 2 | QR | QR | QR | ++-------+-------+-------+-------+ +| 3 | QR | QR | NQ | ++-------+-------+-------+-------+ + +<component name> is classified as CLAS_OUT=<Q|QR|NQ> + + +Step 4: Document all results and rationale for choosing (P) and (C) and (CLAS_OUT) +---------------------------------------------------------------------------------- +This document + + +Step 5: Based on (CLAS_OUT) select the activities +------------------------------------------------- + +| As soon as the change request containing this is in status "Accepted", the module safety plan for the component development is adapted based on the following: (select according to above result) +| - Q: Follow the processes for qualification of software components in a safety context. +| - QR: Follow the process for pre-existing software architectural elements +| - NQ: Do no use this element in safety context diff --git a/docs/modules/persistency/kvs/docs/index.rst b/docs/modules/persistency/kvs/docs/index.rst new file mode 100644 index 0000000000..d57f2f1674 --- /dev/null +++ b/docs/modules/persistency/kvs/docs/index.rst @@ -0,0 +1,180 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _component_template: + +KVS (Key Value Store) +##################### + +.. note:: Document header + +.. document:: [Your Component Name] + :id: doc__component_name + :status: draft + :safety: ASIL_D + :realizes: wp__cmpt_request + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``document`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Abstract +======== + +[A short (~200 word) description of the contribution being addressed.] + + +Motivation +========== + +[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] + + .. note:: + The motivation is critical for CRs that want to change the existing components. + It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. + Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. + CRs submissions without sufficient motivation may be rejected. + + + +Rationale +========= + +[Describe why particular design decisions were made.] + + + .. note:: + The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. + + +Specification +============= + +[Describe the requirements, architecture of any new component.] or +[Describe the change to requirements, architecture, implementation, documentation of any change request.] + + .. note:: + A CR shall specify the component requirements as part of our platform/project. + Thereby the :need:`rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). + + + +Backwards Compatibility +======================= + +[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] + + +Security Impact +=============== + +[How could a malicious user take advantage of this new/modified component?] + + .. note:: + If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which security requirements are affected or has to be changed? +Could the new/modified component enable new threat scenarios? +Could the new/modified component enable new attack paths? +Could the new/modified component impact functional safety? +If applicable, which additional security measures must be implemented to mitigate the risk? + + .. note:: + Use Security Software Critically Analysis, Vulnerability Analysis. + [Methods will be defined later in Process area Security Analysis] + + +Safety Impact +============= + +[How could the safety be impacted by the new/modified component?] + + .. note:: + If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. + +Which safety requirements are affected or has to be changed? +Could the new/modified component be a potential common cause or cascading failure initiator? +If applicable, which additional safety measures must be implemented to mitigate the risk? + + .. note:: + Use Dependency Failure Analysis and/or Safety Software Critically Analysis. + [Methods will be defined later in Process area Safety Analysis] + +For new feature/component contributions: + +[What is the expected ASIL level?] +[What is the expected classification of the contribution?] + + .. note:: + Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`gd_temp__component_classification`. + +License Impact +============== + +[How could the copyright impacted by the license of the new contribution?] + + +How to Teach This +================= + +[How to teach users, new and experienced, how to apply the CR to their work.] + + .. note:: + For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. + + + +Rejected Ideas +============== + +[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] + + .. note:: + Throughout the discussion of a CR, various ideas will be proposed which are not accepted. + Those rejected ideas should be recorded along with the reasoning as to why they were rejected. + This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. + In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. + + + +Open Issues +=========== + +[Any points that are still being decided/discussed.] + + .. note:: + While a CR is in draft, ideas can come up which warrant further discussion. + Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. + This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. + + + +Footnotes +========= + +[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] + +.. toctree:: + :hidden: + + requirements/index.rst + architecture/index.rst + safety_analysis/fmea.rst + safety_analysis/dfa.rst + component_classification.rst diff --git a/docs/modules/persistency/kvs/docs/requirements/index.rst b/docs/modules/persistency/kvs/docs/requirements/index.rst new file mode 100644 index 0000000000..9e0d6d7b6f --- /dev/null +++ b/docs/modules/persistency/kvs/docs/requirements/index.rst @@ -0,0 +1,72 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Requirements +############ + +.. document:: [Your Component Name] Requirements + :id: doc__component_name_requirements + :status: draft + :safety: ASIL_D + :realizes: wp__requirements__comp + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +<Headlines (for the list of requirements if structuring is needed)> +=================================================================== + +.. comp_req:: Some Title + :id: comp_req__component_name__some_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :satisfies: feat_req__feature_name__some_title + :status: invalid + + The Component shall do xyz to another component to bring it to this condition at this time + + Note: (optional, not to be verified) + +.. attention:: + The above directive must be updated according to your component requirements. + + - Replace the example content by the real content for your first requirement + - Set the status to valid and start the review/merge process + - Add other needed requirements for your component + +.. aou_req:: Next Title + :id: aou_req__component_name__next_title + :reqtype: Process + :security: YES + :safety: ASIL_D + :status: invalid + + The Component User shall do xyz to use the component safely + +.. attention:: + The above directives must be updated according to your feature requirements. + + - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) + - Set the status to valid and start the review/merge process + - Add other needed requirements for your feature + +.. needextend:: "component_name" in id + :+tags: component_name diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst b/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst new file mode 100644 index 0000000000..1626d6304c --- /dev/null +++ b/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst @@ -0,0 +1,53 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Dependent Failure Analysis +========================== + +.. document:: [Your Component Name] DFA + :id: doc__component_name_dfa + :status: draft + :safety: ASIL_D + :realizes: wp__sw_component_dfa + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_dfa`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Dependent Failure Intitiators +----------------------------- + +.. code-block:: rst + + .. comp_saf_dfa:: <Element descriptor> + :id: comp_saf_DFA__<Component>__<Element descriptor> + :violation_id: <ID from Dependent Failure Initiators list :need:`gd_guidl__dfi`> + :violation_effect: <Effect caused by the initiator (leading to a violation of a safety goal)> + :verifies: <ID from Component Architecture> + :mitigated_by: < NONE|ID from Component Requirement> + :sufficient: <yes|no> + :argument: <text to argument why measure is sufficient> + :status: <valid|invalid> + +.. attention:: + The above directive must be updated according to your component DFA. + + - Remove the ``code-block`` + - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst b/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst new file mode 100644 index 0000000000..319c63d4ef --- /dev/null +++ b/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst @@ -0,0 +1,53 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Safety Analysis : FMEA +====================== + +.. document:: [Your Component Name] FMEA + :id: doc__component_name_fmea + :status: draft + :safety: ASIL_D + :realizes: wp__sw_component_safety_analysis + :tags: template + +.. attention:: + The above directive must be updated according to your Component. + + - Modify ``Your Component Name`` to be your Component Name + - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_fmea`` + - Adjust ``status`` to be ``valid`` + - Adjust ``safety`` and ``tags`` according to your needs + +Failure Mode List +----------------- + +.. code-block:: rst + + .. comp_saf_fmea:: <Element descriptor> + :id: comp_saf_FMEA__<Component>__<Element descriptor> + :failure_mode: <ID from fault model :need:`gd_guidl__fault_models`> + :failure_effect: <Effect caused by the failure (leading to a violation of a safety goal)> + :verifies: <ID from Component Architecture> + :mitigated_by: < NONE|ID from Component Requirement> + :sufficient: <yes|no> + :argument: <text to argument why measure is sufficient> + :status: <valid|invalid> + +.. attention:: + The above directive must be updated according to your component FMEA. + + - Remove the ``code-block`` + - Fill in all the needed information in the <brackets> From 7cf3d9b317f4b81a9320c06d067ed60b18cc590b Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Mon, 2 Jun 2025 11:00:59 +0200 Subject: [PATCH 016/102] persistency_kvs: move KVS reqs to new folder structure Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/file-access/index.rst | 16 -- docs/features/persistency/index.rst | 136 +++++++++++++++- docs/features/persistency/kvs/index.rst | 147 ------------------ .../{kvs => }/requirements/index.rst | 0 4 files changed, 131 insertions(+), 168 deletions(-) delete mode 100644 docs/features/persistency/file-access/index.rst delete mode 100644 docs/features/persistency/kvs/index.rst rename docs/features/persistency/{kvs => }/requirements/index.rst (100%) diff --git a/docs/features/persistency/file-access/index.rst b/docs/features/persistency/file-access/index.rst deleted file mode 100644 index ebfd99f141..0000000000 --- a/docs/features/persistency/file-access/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -File Access -########### diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index 6516dc4288..ac16cf0b2a 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -1,6 +1,6 @@ .. # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation + # Copyright (c) 2025 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,10 +12,136 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Persistency -########### +Key-Value-Storage +################# + +.. document:: Persistency Key-Value-Storage + :id: doc__persistency_kvs + :status: draft + :safety: ASIL_B + :tags: contribution_request, feature_request .. toctree:: + :hidden: + + requirements/index.rst + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``persistency_kvs`` + + +Abstract +======== + +This feature request describes the key-value storage (KVS) that is needed by +applications to store either temporary or permanent data in an easy way that +conforms to most programming languages that provide a hash, hashmap, dictionary +or similar data structure. Access to the KVS is possible from any support +language through language specific interfaces. + + +Motivation +========== + +The current solutions available mostly don't meet the specific needs of the +S-CORE project like storing specific datatypes without a BASE64 conversation or +having no rollback/replay feature. Also the integration into analysis tools is +simpler when the solution grows with the needs instead having to adapt existing +data structures through wrapppers. Especially in the focus of security it will +be possible to build a system that integrates the layers from scratch and +provide them as API to any language whilst still using Rust as the backend. + +A main USP of the solution will be the integration of a tracing framework that +allows to understand how events also in the context of other events interact. + +A key-value storage is used within many applications to store e.g. +configuration data and is therefore seen crucial for the Eclipse S-CORE +platform. + + +Rationale +========= + +1. There are multiple key-value storages allowed per application. + +To allow for data separation and different levels of security, each application +is allowed to have multiple KVS. + +2. There must be an update mechanism from different versions of a KVS to another version. + +Staying compatible through updates and rollbacks is a main requirement for the +project. + +3. The same KVS should be read/writable from C++ & Rust and any other language. + +Having a flexible interface allows to focus on solutions where the language +fits the needs. + +4. KVS should store default values. + +If possible, all keys should return a configurable default value or the access +should return an error if the key needs to be written first. + +5. KVS should use a simple data representation. + +The KVS should use a data representation that supports versioned up- and +downgrading like JSON or Cap'n Proto and is easily debuggable by the developer. + +6. Integrity of the KVS should be checked. + +The KVS is always be in a consistent state that either provides the currently +stored data or if not possible the previous snapshot. + + +Backwards Compatibility +======================= + +The API for the specific language tries to represent the language specific +implementation like hashmaps or dictionaries to be mostly backwards compatible +to already existing key-value-storage usage cases. Access without a safe error +handling path, like the array-operator in Rust which can panic, must be +avoided. + + +Security Impact +=============== + +Access to the key-value-storage would allow a malicious user to control the +behaviour of the device so it needs to be secured as much as possible, like +only providing debug access when a debug firmware image is installed. + + +Safety Impact +============= + + .. note:: + One key-value storage should not be used within different processes (freedom from interference) -> To be added to AoUs? + +[How could the safety be impacted by the new feature?] + + .. note:: + If there are safety concerns in relation to the Feature Request, those concerns should be explicitly written out to make sure reviewers of the Feature Request are aware of them. + ToDo - Link to the Safety Impact Method + +[What is the expected ASIL level?] +[What is the expected classification of the contribution?] + + .. note:: + Use the component classification method here to classify your component, if it shall to be used in a safety context: (TODO: add link to component classification). + + +License Impact +============== + + .. note:: + The key-value storage itself uses the Apache-2.0 license. Licenses of + used libraries are need to be checked. + - file-access/index.rst - kvs/index.rst +How to Teach This +================= diff --git a/docs/features/persistency/kvs/index.rst b/docs/features/persistency/kvs/index.rst deleted file mode 100644 index ac16cf0b2a..0000000000 --- a/docs/features/persistency/kvs/index.rst +++ /dev/null @@ -1,147 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Key-Value-Storage -################# - -.. document:: Persistency Key-Value-Storage - :id: doc__persistency_kvs - :status: draft - :safety: ASIL_B - :tags: contribution_request, feature_request - -.. toctree:: - :hidden: - - requirements/index.rst - - -Feature flag -============ - -To activate this feature, use the following feature flag: - -``persistency_kvs`` - - -Abstract -======== - -This feature request describes the key-value storage (KVS) that is needed by -applications to store either temporary or permanent data in an easy way that -conforms to most programming languages that provide a hash, hashmap, dictionary -or similar data structure. Access to the KVS is possible from any support -language through language specific interfaces. - - -Motivation -========== - -The current solutions available mostly don't meet the specific needs of the -S-CORE project like storing specific datatypes without a BASE64 conversation or -having no rollback/replay feature. Also the integration into analysis tools is -simpler when the solution grows with the needs instead having to adapt existing -data structures through wrapppers. Especially in the focus of security it will -be possible to build a system that integrates the layers from scratch and -provide them as API to any language whilst still using Rust as the backend. - -A main USP of the solution will be the integration of a tracing framework that -allows to understand how events also in the context of other events interact. - -A key-value storage is used within many applications to store e.g. -configuration data and is therefore seen crucial for the Eclipse S-CORE -platform. - - -Rationale -========= - -1. There are multiple key-value storages allowed per application. - -To allow for data separation and different levels of security, each application -is allowed to have multiple KVS. - -2. There must be an update mechanism from different versions of a KVS to another version. - -Staying compatible through updates and rollbacks is a main requirement for the -project. - -3. The same KVS should be read/writable from C++ & Rust and any other language. - -Having a flexible interface allows to focus on solutions where the language -fits the needs. - -4. KVS should store default values. - -If possible, all keys should return a configurable default value or the access -should return an error if the key needs to be written first. - -5. KVS should use a simple data representation. - -The KVS should use a data representation that supports versioned up- and -downgrading like JSON or Cap'n Proto and is easily debuggable by the developer. - -6. Integrity of the KVS should be checked. - -The KVS is always be in a consistent state that either provides the currently -stored data or if not possible the previous snapshot. - - -Backwards Compatibility -======================= - -The API for the specific language tries to represent the language specific -implementation like hashmaps or dictionaries to be mostly backwards compatible -to already existing key-value-storage usage cases. Access without a safe error -handling path, like the array-operator in Rust which can panic, must be -avoided. - - -Security Impact -=============== - -Access to the key-value-storage would allow a malicious user to control the -behaviour of the device so it needs to be secured as much as possible, like -only providing debug access when a debug firmware image is installed. - - -Safety Impact -============= - - .. note:: - One key-value storage should not be used within different processes (freedom from interference) -> To be added to AoUs? - -[How could the safety be impacted by the new feature?] - - .. note:: - If there are safety concerns in relation to the Feature Request, those concerns should be explicitly written out to make sure reviewers of the Feature Request are aware of them. - ToDo - Link to the Safety Impact Method - -[What is the expected ASIL level?] -[What is the expected classification of the contribution?] - - .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: (TODO: add link to component classification). - - -License Impact -============== - - .. note:: - The key-value storage itself uses the Apache-2.0 license. Licenses of - used libraries are need to be checked. - - -How to Teach This -================= diff --git a/docs/features/persistency/kvs/requirements/index.rst b/docs/features/persistency/requirements/index.rst similarity index 100% rename from docs/features/persistency/kvs/requirements/index.rst rename to docs/features/persistency/requirements/index.rst From 4debbe4fad76a20c204f9c5b9c4fdb9c0eb320b5 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Mon, 2 Jun 2025 11:01:04 +0200 Subject: [PATCH 017/102] persistency_kvs: renamed kvs to persistency in key names Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/requirements/index.rst | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/features/persistency/requirements/index.rst b/docs/features/persistency/requirements/index.rst index b2205785a5..a9cf044a00 100644 --- a/docs/features/persistency/requirements/index.rst +++ b/docs/features/persistency/requirements/index.rst @@ -16,7 +16,7 @@ Requirements ############ .. feat_req:: C++ & Rust Interoperability - :id: feat_req__kvs__cpp_rust_interoperability + :id: feat_req__persistency__cpp_rust_interop :reqtype: Non-Functional :security: NO :safety: QM @@ -26,7 +26,7 @@ Requirements The KVS system shall provide access through both C++ and Rust interfaces. .. feat_req:: Maximum Size - :id: feat_req__kvs__maximum_size + :id: feat_req__persistency__maximum_size :reqtype: Functional :security: NO :safety: ASIL_B @@ -36,7 +36,7 @@ Requirements The KVS system shall support specification of its maximum capacity at compile time. .. feat_req:: Multiple KVS per Software Architecture Element - :id: feat_req__kvs__multiple_kvs + :id: feat_req__persistency__multiple_kvs :reqtype: Functional :security: NO :safety: ASIL_B @@ -46,7 +46,7 @@ Requirements The KVS system shall allow instantiating multiple independent stores per software architecture element. .. feat_req:: Supported Datatypes (Keys) - :id: feat_req__kvs__supported_datatypes_keys + :id: feat_req__persistency__support_datatype_keys :reqtype: Functional :security: NO :safety: ASIL_B @@ -56,7 +56,7 @@ Requirements The KVS system shall support UTF-8 encoded strings as valid key types. .. feat_req:: Supported Datatypes (Values) - :id: feat_req__kvs__supported_datatypes_values + :id: feat_req__persistency__support_datatype_value :reqtype: Functional :security: NO :safety: ASIL_B @@ -67,7 +67,7 @@ Requirements The supported datatypes shall match those used by the IPC feature. .. feat_req:: Default Values - :id: feat_req__kvs__default_values + :id: feat_req__persistency__default_values :reqtype: Functional :security: NO :safety: ASIL_B @@ -77,7 +77,7 @@ Requirements The KVS system shall support predefined default values for keys. .. feat_req:: Default Value Retrieval - :id: feat_req__kvs__default_value_retrieval + :id: feat_req__persistency__default_value_get :reqtype: Functional :security: NO :safety: ASIL_B @@ -87,7 +87,7 @@ Requirements The KVS system shall support retrieving the default value associated with a key. .. feat_req:: Default Value Reset - :id: feat_req__kvs__default_value_reset + :id: feat_req__persistency__default_value_reset :reqtype: Functional :security: NO :safety: ASIL_B @@ -97,7 +97,7 @@ Requirements The KVS system shall support resetting a single key or all keys to their respective default values. .. feat_req:: Persistency - :id: feat_req__kvs__persistency + :id: feat_req__persistency__persistency :reqtype: Functional :security: NO :safety: ASIL_B @@ -107,7 +107,7 @@ Requirements The KVS system shall persist stored data and provide an API to explicitly trigger persistence. .. feat_req:: Integrity Check - :id: feat_req__kvs__integrity_check + :id: feat_req__persistency__integrity_check :reqtype: Functional :security: NO :safety: ASIL_B @@ -118,7 +118,7 @@ Requirements Note: Implementation depends on AoUs. .. feat_req:: Versioning - :id: feat_req__kvs__versioning + :id: feat_req__persistency__versioning :reqtype: Functional :security: NO :safety: ASIL_B @@ -128,7 +128,7 @@ Requirements The KVS system shall support versioning for different layout configurations. .. feat_req:: Update Mechanism - :id: feat_req__kvs__update_mechanism + :id: feat_req__persistency__update_mechanism :reqtype: Functional :security: NO :safety: ASIL_B @@ -138,7 +138,7 @@ Requirements The KVS system shall implement mechanisms to upgrade from one version to another, including multi-version jumps. .. feat_req:: Snapshots - :id: feat_req__kvs__snapshots + :id: feat_req__persistency__snapshots :reqtype: Functional :security: NO :safety: ASIL_B @@ -149,7 +149,7 @@ Requirements Snapshots shall also be deletable. .. feat_req:: Tooling - :id: feat_req__kvs__tooling + :id: feat_req__persistency__tooling :reqtype: Non-Functional :security: NO :safety: ASIL_B @@ -159,7 +159,7 @@ Requirements The KVS system shall provide tooling support for viewing and modifying key-value pairs during development and debugging. .. feat_req:: Stable APIs - :id: feat_req__kvs__stable_api + :id: feat_req__persistency__stable_api :reqtype: Non-Functional :security: NO :safety: QM @@ -169,7 +169,7 @@ Requirements The KVS API shall remain stable throughout its lifecycle while enabling the addition of new functionalities. .. feat_req:: Variant management support - :id: feat_req__kvs__variant_management + :id: feat_req__persistency__variant_management :reqtype: Non-Functional :security: NO :safety: QM @@ -179,7 +179,7 @@ Requirements The KVS shall ensure compatibility across different architectures and versions. .. feat_req:: Set default key values via file - :id: feat_req__kvs__default_value_file + :id: feat_req__persistency__default_value_file :reqtype: Functional :security: NO :safety: QM @@ -189,7 +189,7 @@ Requirements The KVS shall support the configuration of default key values using an external file. .. feat_req:: Configure limits via file - :id: feat_req__kvs__config_file + :id: feat_req__persistency__config_file :reqtype: Functional :security: NO :safety: QM @@ -199,7 +199,7 @@ Requirements The KVS shall support the configuration of memory and other resource limits via a configuration file. .. feat_req:: Store persistent data - :id: feat_req__kvs__persist_data + :id: feat_req__persistency__persist_data :reqtype: Functional :security: NO :safety: QM @@ -209,7 +209,7 @@ Requirements The KVS shall support storing and loading its data to and from persistent storage. .. feat_req:: Support engineering and field mode - :id: feat_req__kvs__dev_mode + :id: feat_req__persistency__dev_mode :reqtype: Functional :security: NO :safety: ASIL_B @@ -220,7 +220,7 @@ Requirements The engineering mode shall allow unrestricted data access. .. feat_req:: Provide an async API - :id: feat_req__kvs__async_api + :id: feat_req__persistency__async_api :reqtype: Functional :security: NO :safety: QM @@ -230,7 +230,7 @@ Requirements The KVS shall provide an asynchronous API for accessing and manipulating data. .. feat_req:: Separate data stores - :id: feat_req__kvs__access_control + :id: feat_req__persistency__access_control :reqtype: Functional :security: NO :safety: QM @@ -240,7 +240,7 @@ Requirements The KVS shall ensure that only authorized components can access individual data stores. .. feat_req:: Data-change events - :id: feat_req__kvs__events + :id: feat_req__persistency__events :reqtype: Functional :security: NO :safety: ASIL_B @@ -252,7 +252,7 @@ Requirements such as when keys are changed or removed. .. feat_req:: Fast access - :id: feat_req__kvs__fast_access + :id: feat_req__persistency__fast_access :reqtype: Non-Functional :security: NO :safety: QM @@ -262,7 +262,7 @@ Requirements The KVS shall ensure that key operations are typically completed within 5 milliseconds. .. feat_req:: Intra-Process Data Access - :id: feat_req__kvs__intra_process_comm + :id: feat_req__persistency__intra_process_comm :reqtype: Functional :security: NO :safety: QM From d37fb7803669f59c036925be8ed335332d26968d Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Fri, 9 May 2025 15:46:52 +0200 Subject: [PATCH 018/102] persistency_kvs: feature architecture Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../_assets/comp_dyn_kvs_key_get.puml | 36 +++++ .../architecture/_assets/kvs_dyn_builder.puml | 29 ++++ .../_assets/kvs_dyn_check_value_default.puml | 24 +++ .../_assets/kvs_dyn_delete_data_key.puml | 16 ++ .../kvs_dyn_flush_local_repr_to_file.puml | 60 ++++++++ .../_assets/kvs_dyn_read_data_key.puml | 20 +++ .../kvs_dyn_read_file_into_local_repr.puml | 49 ++++++ .../_assets/kvs_dyn_restore_snapshot.puml | 19 +++ .../_assets/kvs_dyn_write_data_key.puml | 11 ++ .../architecture/_assets/kvs_interface.puml | 23 +++ .../architecture/_assets/kvs_static_view.puml | 32 ++++ .../kvs/architecture/feature_architecture.rst | 139 ++++++++++++++++++ .../persistency/kvs/architecture/index.rst | 25 ++++ 13 files changed, 483 insertions(+) create mode 100644 docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml create mode 100644 docs/features/persistency/kvs/architecture/feature_architecture.rst create mode 100644 docs/features/persistency/kvs/architecture/index.rst diff --git a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml new file mode 100644 index 0000000000..d99890f239 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml @@ -0,0 +1,36 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +@startuml + +participant "Feature User" as actor +participant "«component» :Lower Level Component 1" as sc1 +participant "«component» :Lower Level Component 3" as sc3 + +actor -> sc1: real operation 3 () +sc1 -> sc3: real operation 9 () + +alt success + sc3 --> sc1: success +else error + sc3 --> sc1: error type +end + +alt success + sc1 --> actor: true +else error + sc1 -> actor: error type +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml new file mode 100644 index 0000000000..24bcfd97c6 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml @@ -0,0 +1,29 @@ +@startuml + +title Sequence Diagram: KVS Builder + +participant "User" as actor +participant "«component» :builder" as builder +participant "«component» :kvs" as kvs + +actor -> builder: Create KVS builder +builder --> actor: KVS builder instance + +actor -> builder: Set need_defaults flag +builder --> actor: KVS builder instance + +actor -> builder: Set need_kvs flag +builder --> actor: KVS builder instance + +actor -> builder: Build KVS instance +builder -> kvs: Open KVS with builder config + +alt kvs-open + kvs --> builder: KVS instance + builder --> actor: KVS instance +else kvs-open-error + kvs --> builder: KVS ErrorCode + builder --> actor: KVS ErrorCode +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml new file mode 100644 index 0000000000..b585fda342 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml @@ -0,0 +1,24 @@ +@startuml + +title Sequence Diagram: Check if Key contains Default Value + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Does key has default value + +alt default-key-exists + alt key-exists + alt default-and-key-match + kvs --> actor: Key contains default value + else key-doesnt-exist + kvs --> actor: Key doesn't containt default value + end + else key-doesnt-exist + kvs --> actor: Key contains default value + end +else default-doesnt-exist + kvs --> actor: Key doesn't contain default value +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml new file mode 100644 index 0000000000..e2b222e311 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml @@ -0,0 +1,16 @@ +@startuml + +title Sequence Diagram: Delete Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Remove key + +alt key-exists + kvs --> actor: Successfully deleted key +else key-doesnt-exist + kvs --> actor: Key-Not-Found-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml new file mode 100644 index 0000000000..c2150a6857 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml @@ -0,0 +1,60 @@ +@startuml + +title Sequence Diagram: Flush Local Representation to Data File + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :snapshot" as snapshot +participant "«component» :TinyJSON" as json_parser +participant "«component» :fs" as fs +participant "«component» :Adler32" as hasher + +actor -> kvs: Flush KVS + +kvs -> json_parser: Generate string from local representation + +alt json-string + json_parser --> kvs: JSON data string +else json-string-error + json_parser --> kvs: JSON generator error + kvs --> actor: JSON generator error +end + +kvs -> snapshot: Rotate snapshots + +alt snapshot-rotate + snapshot -> kvs: Snapshots rotated +else snapshot-rotate-error + snapshot --> kvs: Snapshot-Rotate-Error + kvs --> actor: Snapshot-Rotate-Error +end + +kvs -> hasher: Create JSON data string hash + +alt hash-created + hasher --> kvs: Data hash +else hash-create-error + hasher --> kvs: Hash-Calc-Error + kvs --> actor: Hash-Calc-Error +end + +kvs -> fs: Write JSON data string to file + +alt file-write + fs --> kvs: File successfully written +else file-write-error + fs --> kvs: File-Write-Error + kvs --> actor: File-Write-Error +end + +kvs -> fs: Write JSON data hash to file + +alt file-hash-write + fs --> kvs: Hash file successfully written + kvs --> actor: Flush successful +else file-hash-write-error + fs --> kvs: File-Hash-Write-Error + kvs --> actor: File-Hash-Write-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml new file mode 100644 index 0000000000..064e248911 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml @@ -0,0 +1,20 @@ +@startuml + +title Sequence Diagram: Read Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Get value for key + +alt key-exists + kvs --> actor: Return value for key +else key-doesnt-exist + alt default-exists + kvs --> actor: Return default value for key + else default-doesnt-exist + kvs --> actor: Key-Not-Found error + end +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml new file mode 100644 index 0000000000..c4cdbaffaa --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml @@ -0,0 +1,49 @@ +@startuml + +title Sequence Diagram: Read Data into Local Representation (KvsValue) + +participant "Builder" as actor +participant "«component» :kvs" as kvs +participant "«component» :TinyJSON" as json_parser +participant "«component» :fs" as fs +participant "«component» :Adler32" as hasher + +actor -> kvs: Open KVS + +kvs -> fs: Read defaults file + +alt file-exists + fs --> kvs: Defaults file content (JSON) +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> fs: Read defaults file hash + +alt file-exists + fs --> kvs: Defaults file hash +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> hasher: Generate defaults file hash +hasher --> kvs: Defaults file generated hash + +alt hash-matches + kvs -> json_parser: Parse JSON data +else hash-match-error + kvs -> actor: Hash-Error +end + +alt parsing-success + json_parser --> kvs: Parsed JSON object +else parsing-based-error + json_parser -> kvs: Parser-Error + kvs -> actor: Parser-Error +end + +kvs --> actor: KVS instance + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml new file mode 100644 index 0000000000..a18eab3b8a --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml @@ -0,0 +1,19 @@ +@startuml + +title Sequence Diagram: Restore Snapshot + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :snapshot" as snapshot + +actor -> kvs: Restore snapshot + +alt snapshot-found + snapshot --> kvs: Snapshot restored into local representation + kvs --> actor: Snapshot restored successfully +else snapshot-error + snapshot --> kvs: Snapshot-Not-Available-Error + kvs --> actor: Snapshot-Not-Available-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml new file mode 100644 index 0000000000..b34c24cc20 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml @@ -0,0 +1,11 @@ +@startuml + +title Sequence Diagram: Write Key to KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Set value for key +kvs --> actor: Value set for key + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml new file mode 100644 index 0000000000..e8e2e1750d --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml @@ -0,0 +1,23 @@ +@startuml + +interface Kvs { + open + flush_on_exit + reset + get_all_keys + key_exists + get_value + get_default_value + has_default_value + set_default_value + set_value + remove_key + flush + snapshot_count + snapshot_max_count + snapshot_restore + get_kvs_filename + get_hash_filename +} + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml new file mode 100644 index 0000000000..e016ae104a --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml @@ -0,0 +1,32 @@ +@startuml +allowmixing + +title Static View - kvs + +!include kvs_interface.puml + + +skinparam package { + BackgroundColor #E0E0D0 + BorderColor Black + backgroundColor<<feature>> yellow +} + +skinparam component { + backgroundColor<<component>> white +} + +' Define Features +package "kvs" <<feature>> { + component kvs <<component>> + component fs <<component>> + component tiny_json <<component>> +} + +kvs -u- Kvs + +kvs ..> tiny_json : use +kvs ..> fs : use + + +@enduml diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst new file mode 100644 index 0000000000..daad3c0b0c --- /dev/null +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -0,0 +1,139 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Architecture : persistency/kvs +==================================================== + +Overview +-------- + +- kvs provides the capability to efficiently store, retrieve, and + manage key-value pairs in a persistent storage system. + +Description +----------- + +- kvs organize data as pairs, where each unique key is associated with a specific value. + The key acts as a unique identifier for getting the value. +- The data is persisted in JSON format to the file system, providing a human-readable, + and widely supported way to store and manage key-value pairs. +- The JSON data persisted is according to RFC-8259. + +Rationale Behind Architecture Decomposition +******************************************* + +- The architecture is decomposed to include a dedicated JSON parser component (TinyJSON) to facilitate the persistent storage of data in JSON format. +- The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. + + +Static Architecture +------------------- + +.. feat_arc_sta:: Static Architecture + :id: feat_arc_sta__kvs__static + :security: YES + :safety: ASIL_B + :includes: feat_arc_int__kvs__interface + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_static_view.puml + +Dynamic Architecture +-------------------- + +.. feat_arc_dyn:: KVS Builder + :id: feat_arc_dyn__kvs__builder_pattern + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_dyn_builder.puml + +.. feat_arc_dyn:: Check if key contains default value + :id: feat_arc_dyn__kvs__check_key_default + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :status: valid + + .. uml:: _assets/kvs_dyn_check_value_default.puml + +.. feat_arc_dyn:: Delete key from KVS instance + :id: feat_arc_dyn__kvs__delete_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_dyn_delete_data_key.puml + +.. feat_arc_dyn:: Flush to permanent storage + :id: feat_arc_dyn__kvs__flush + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml + +.. feat_arc_dyn:: Read key value + :id: feat_arc_dyn__kvs__read_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :status: valid + + .. uml:: _assets/kvs_dyn_read_data_key.puml + +.. feat_arc_dyn:: Read data from permanent storage + :id: feat_arc_dyn__kvs__read_data_from_storage + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml + +.. feat_arc_dyn:: Write value to key + :id: feat_arc_dyn__kvs__write_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values + :status: valid + + .. uml:: _assets/kvs_dyn_write_data_key.puml + +.. feat_arc_dyn:: Restore snapshop + :id: feat_arc_dyn__kvs__snapshot_restore + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency + :status: valid + + .. uml:: _assets/kvs_dyn_restore_snapshot.puml + + +Logical Interfaces +------------------ + +.. feat_arc_int:: Ikvs + :id: feat_arc_int__kvs__interface + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__stable_api + :status: valid + + .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst new file mode 100644 index 0000000000..335d087369 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/index.rst @@ -0,0 +1,25 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Architecture +############# + +.. note:: + For now we store the component architecture in the feature tree, because multi-repo docs are not yet supported. + Once this support becomes available the component architecture will be moved to the module. + +.. toctree:: + :titlesonly: + + feature_architecture From 5d97f893767fbfdef65397592f7454cb06ddaa2a Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Mon, 12 May 2025 13:59:57 +0200 Subject: [PATCH 019/102] persistency_kvs: synced components in feature architecture Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../architecture/_assets/kvs_dyn_builder.puml | 26 ++++++-------- .../kvs_dyn_flush_local_repr_to_file.puml | 16 ++++----- .../kvs_dyn_read_file_into_local_repr.puml | 6 ++-- .../_assets/kvs_dyn_restore_snapshot.puml | 7 ++-- .../kvs/architecture/feature_architecture.rst | 35 +++++++------------ 5 files changed, 34 insertions(+), 56 deletions(-) diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml index 24bcfd97c6..3e1744068a 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml @@ -3,27 +3,23 @@ title Sequence Diagram: KVS Builder participant "User" as actor -participant "«component» :builder" as builder participant "«component» :kvs" as kvs -actor -> builder: Create KVS builder -builder --> actor: KVS builder instance +actor -> kvs: Create KVS builder +kvs --> actor: KVS builder instance -actor -> builder: Set need_defaults flag -builder --> actor: KVS builder instance +actor -> kvs: Set need_defaults flag +kvs --> actor: KVS builder instance -actor -> builder: Set need_kvs flag -builder --> actor: KVS builder instance +actor -> kvs: Set need_kvs flag +kvs --> actor: KVS builder instance -actor -> builder: Build KVS instance -builder -> kvs: Open KVS with builder config +actor -> kvs: Build KVS instance -alt kvs-open - kvs --> builder: KVS instance - builder --> actor: KVS instance -else kvs-open-error - kvs --> builder: KVS ErrorCode - builder --> actor: KVS ErrorCode +alt kvs-builder-success + kvs --> actor: KVS instance with builder config +else kvs-builder-error + kvs --> actor: KVS ErrorCode end @enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml index c2150a6857..e48826314f 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml @@ -4,10 +4,8 @@ title Sequence Diagram: Flush Local Representation to Data File participant "User" as actor participant "«component» :kvs" as kvs -participant "«component» :snapshot" as snapshot participant "«component» :TinyJSON" as json_parser participant "«component» :fs" as fs -participant "«component» :Adler32" as hasher actor -> kvs: Flush KVS @@ -20,21 +18,19 @@ else json-string-error kvs --> actor: JSON generator error end -kvs -> snapshot: Rotate snapshots +kvs -> kvs: Rotate snapshots -alt snapshot-rotate - snapshot -> kvs: Snapshots rotated +alt snapshot-rotate-success + kvs --> kvs: Snapshots rotated else snapshot-rotate-error - snapshot --> kvs: Snapshot-Rotate-Error kvs --> actor: Snapshot-Rotate-Error end -kvs -> hasher: Create JSON data string hash +kvs -> kvs: Create JSON data hash -alt hash-created - hasher --> kvs: Data hash +alt hash-created-success + kvs -> kvs: Data hash else hash-create-error - hasher --> kvs: Hash-Calc-Error kvs --> actor: Hash-Calc-Error end diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml index c4cdbaffaa..aed61479b1 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml @@ -6,7 +6,6 @@ participant "Builder" as actor participant "«component» :kvs" as kvs participant "«component» :TinyJSON" as json_parser participant "«component» :fs" as fs -participant "«component» :Adler32" as hasher actor -> kvs: Open KVS @@ -28,10 +27,9 @@ else file-based-error kvs -> actor: File-Error end -kvs -> hasher: Generate defaults file hash -hasher --> kvs: Defaults file generated hash +kvs -> kvs: Generate defaults file hash -alt hash-matches +alt hash-match-success kvs -> json_parser: Parse JSON data else hash-match-error kvs -> actor: Hash-Error diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml index a18eab3b8a..17eb75b382 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml @@ -4,15 +4,12 @@ title Sequence Diagram: Restore Snapshot participant "User" as actor participant "«component» :kvs" as kvs -participant "«component» :snapshot" as snapshot actor -> kvs: Restore snapshot -alt snapshot-found - snapshot --> kvs: Snapshot restored into local representation +alt snapshot-restore-success kvs --> actor: Snapshot restored successfully -else snapshot-error - snapshot --> kvs: Snapshot-Not-Available-Error +else snapshot-restore-error kvs --> actor: Snapshot-Not-Available-Error end diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index daad3c0b0c..cfa57b1bdb 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -44,8 +44,8 @@ Static Architecture :id: feat_arc_sta__kvs__static :security: YES :safety: ASIL_B - :includes: feat_arc_int__kvs__interface - :fulfils: feat_req__kvs__safety_asil_b + :includes: logic_arc_int__kvs__interface + :fulfils: :status: valid .. uml:: _assets/kvs_static_view.puml @@ -53,20 +53,11 @@ Static Architecture Dynamic Architecture -------------------- -.. feat_arc_dyn:: KVS Builder - :id: feat_arc_dyn__kvs__builder_pattern - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b - :status: valid - - .. uml:: _assets/kvs_dyn_builder.puml - .. feat_arc_dyn:: Check if key contains default value :id: feat_arc_dyn__kvs__check_key_default :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :fulfils: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval :status: valid .. uml:: _assets/kvs_dyn_check_value_default.puml @@ -75,7 +66,7 @@ Dynamic Architecture :id: feat_arc_dyn__kvs__delete_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b + :fulfils: feat_req__kvs__events :status: valid .. uml:: _assets/kvs_dyn_delete_data_key.puml @@ -84,7 +75,7 @@ Dynamic Architecture :id: feat_arc_dyn__kvs__flush :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :fulfils: feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots :status: valid .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml @@ -93,7 +84,7 @@ Dynamic Architecture :id: feat_arc_dyn__kvs__read_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :fulfils: feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval :status: valid .. uml:: _assets/kvs_dyn_read_data_key.puml @@ -102,7 +93,7 @@ Dynamic Architecture :id: feat_arc_dyn__kvs__read_data_from_storage :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :fulfils: feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots :status: valid .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml @@ -111,16 +102,16 @@ Dynamic Architecture :id: feat_arc_dyn__kvs__write_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values + :fulfils: feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values :status: valid .. uml:: _assets/kvs_dyn_write_data_key.puml -.. feat_arc_dyn:: Restore snapshop +.. feat_arc_dyn:: Restore snapshot :id: feat_arc_dyn__kvs__snapshot_restore :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency + :fulfils: feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency :status: valid .. uml:: _assets/kvs_dyn_restore_snapshot.puml @@ -129,11 +120,11 @@ Dynamic Architecture Logical Interfaces ------------------ -.. feat_arc_int:: Ikvs - :id: feat_arc_int__kvs__interface +.. logic_arc_int:: Ikvs + :id: logic_arc_int__kvs__interface :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__stable_api + :fulfils: feat_req__kvs__stable_api :status: valid .. uml:: _assets/kvs_interface.puml From 63257843f8a6d137e13ae86520b1eb3bf5a5b55e Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 14 May 2025 10:20:59 +0200 Subject: [PATCH 020/102] persistency_kvs: integrate review points from Volker See https://github.com/eclipse-score/score/pull/1068 Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/kvs/architecture/feature_architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index cfa57b1bdb..56958fb0d3 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -13,7 +13,7 @@ # ******************************************************************************* Feature Architecture : persistency/kvs -==================================================== +====================================== Overview -------- From 152db720ced2dc0d5b05494a86314c8c3ed2141a Mon Sep 17 00:00:00 2001 From: vinod reddy gopi reddy <vinodreddy.gopireddy@qorix.ai> Date: Tue, 20 May 2025 11:34:03 +0200 Subject: [PATCH 021/102] docs: added module and corrected the interface in puml --- .../_assets/comp_dyn_kvs_key_get.puml | 36 ------------------- .../architecture/_assets/kvs_interface.puml | 2 +- .../architecture/_assets/kvs_static_view.puml | 8 +++-- .../kvs/architecture/feature_architecture.rst | 2 +- 4 files changed, 7 insertions(+), 41 deletions(-) delete mode 100644 docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml deleted file mode 100644 index d99890f239..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml +++ /dev/null @@ -1,36 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -@startuml - -participant "Feature User" as actor -participant "«component» :Lower Level Component 1" as sc1 -participant "«component» :Lower Level Component 3" as sc3 - -actor -> sc1: real operation 3 () -sc1 -> sc3: real operation 9 () - -alt success - sc3 --> sc1: success -else error - sc3 --> sc1: error type -end - -alt success - sc1 --> actor: true -else error - sc1 -> actor: error type -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml index e8e2e1750d..85aef961c5 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml @@ -1,6 +1,6 @@ @startuml -interface Kvs { +interface IKvs { open flush_on_exit reset diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml index e016ae104a..33de594e4c 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml @@ -9,7 +9,7 @@ title Static View - kvs skinparam package { BackgroundColor #E0E0D0 BorderColor Black - backgroundColor<<feature>> yellow + backgroundColor<<module>> lightgreen } skinparam component { @@ -17,13 +17,15 @@ skinparam component { } ' Define Features -package "kvs" <<feature>> { +package "persistency" <<module>> { component kvs <<component>> component fs <<component>> component tiny_json <<component>> } -kvs -u- Kvs + + +kvs --> IKvs : implements kvs ..> tiny_json : use kvs ..> fs : use diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index 56958fb0d3..eb5bcde9ba 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -45,7 +45,7 @@ Static Architecture :security: YES :safety: ASIL_B :includes: logic_arc_int__kvs__interface - :fulfils: + :fulfils: feat_req__kvs__persistency :status: valid .. uml:: _assets/kvs_static_view.puml From 59b91dceab24e923d4d8fa781ec7cd3c90d8dc04 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Tue, 20 May 2025 13:06:42 +0200 Subject: [PATCH 022/102] persistency_kvs: map all dynamic fulfilled feature reqs to static arch Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/kvs/architecture/feature_architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index eb5bcde9ba..b045b5d5ca 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -45,7 +45,7 @@ Static Architecture :security: YES :safety: ASIL_B :includes: logic_arc_int__kvs__interface - :fulfils: feat_req__kvs__persistency + :fulfils: feat_req__kvs__default_value_retrieval,feat_req__kvs__default_values,feat_req__kvs__events,feat_req__kvs__integrity_check,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__stable_api,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values :status: valid .. uml:: _assets/kvs_static_view.puml From cdeab97a9125918e52c822b0610e6b510b253618 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 28 May 2025 10:36:03 +0200 Subject: [PATCH 023/102] persistency_kvs: integrated review comments from feature architecture Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/kvs/architecture/_assets/kvs_dyn_builder.puml | 2 +- .../kvs/architecture/_assets/kvs_dyn_check_value_default.puml | 2 +- .../_assets/kvs_dyn_flush_local_repr_to_file.puml | 2 +- .../_assets/kvs_dyn_read_file_into_local_repr.puml | 4 ++-- .../persistency/kvs/architecture/_assets/kvs_interface.puml | 2 -- .../persistency/kvs/architecture/_assets/kvs_static_view.puml | 4 ++-- .../persistency/kvs/architecture/feature_architecture.rst | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml index 3e1744068a..a1b25fe473 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml @@ -1,6 +1,6 @@ @startuml -title Sequence Diagram: KVS Builder +title Sequence Diagram: Build KVS Instance participant "User" as actor participant "«component» :kvs" as kvs diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml index b585fda342..01baa2727f 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml @@ -5,7 +5,7 @@ title Sequence Diagram: Check if Key contains Default Value participant "User" as actor participant "«component» :kvs" as kvs -actor -> kvs: Does key has default value +actor -> kvs: Does key have default value alt default-key-exists alt key-exists diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml index e48826314f..947cf782eb 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml @@ -4,7 +4,7 @@ title Sequence Diagram: Flush Local Representation to Data File participant "User" as actor participant "«component» :kvs" as kvs -participant "«component» :TinyJSON" as json_parser +participant "«component» :json" as json_parser participant "«component» :fs" as fs actor -> kvs: Flush KVS diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml index aed61479b1..4a154d24df 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml @@ -2,9 +2,9 @@ title Sequence Diagram: Read Data into Local Representation (KvsValue) -participant "Builder" as actor +participant "User" as actor participant "«component» :kvs" as kvs -participant "«component» :TinyJSON" as json_parser +participant "«component» :json" as json_parser participant "«component» :fs" as fs actor -> kvs: Open KVS diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml index 85aef961c5..46f65a27cc 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml @@ -16,8 +16,6 @@ interface IKvs { snapshot_count snapshot_max_count snapshot_restore - get_kvs_filename - get_hash_filename } @enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml index 33de594e4c..ebb646f285 100644 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml @@ -20,14 +20,14 @@ skinparam component { package "persistency" <<module>> { component kvs <<component>> component fs <<component>> - component tiny_json <<component>> + component json <<component>> } kvs --> IKvs : implements -kvs ..> tiny_json : use +kvs ..> json : use kvs ..> fs : use diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index b045b5d5ca..26718a6472 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -33,7 +33,7 @@ Description Rationale Behind Architecture Decomposition ******************************************* -- The architecture is decomposed to include a dedicated JSON parser component (TinyJSON) to facilitate the persistent storage of data in JSON format. +- The architecture is decomposed to include a dedicated JSON parser component (json) to facilitate the persistent storage of data in JSON format. - The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. From 6fa4e3c8b2af5df1bff0b7ae3d61fdaf970d8e08 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Mon, 2 Jun 2025 13:03:44 +0200 Subject: [PATCH 024/102] persistency_kvs: move KVS arch to new folder structure Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../architecture/_assets/kvs_dyn_builder.puml | 0 .../_assets/kvs_dyn_check_value_default.puml | 0 .../_assets/kvs_dyn_delete_data_key.puml | 0 .../kvs_dyn_flush_local_repr_to_file.puml | 0 .../_assets/kvs_dyn_read_data_key.puml | 0 .../kvs_dyn_read_file_into_local_repr.puml | 0 .../_assets/kvs_dyn_restore_snapshot.puml | 0 .../_assets/kvs_dyn_write_data_key.puml | 0 .../architecture/_assets/kvs_interface.puml | 0 .../architecture/_assets/kvs_static_view.puml | 0 .../index.rst} | 38 +++++++++---------- docs/features/persistency/index.rst | 1 + .../persistency/kvs/architecture/index.rst | 25 ------------ 13 files changed, 20 insertions(+), 44 deletions(-) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_builder.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_check_value_default.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_delete_data_key.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_read_data_key.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_restore_snapshot.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_dyn_write_data_key.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_interface.puml (100%) rename docs/features/persistency/{kvs => }/architecture/_assets/kvs_static_view.puml (100%) rename docs/features/persistency/{kvs/architecture/feature_architecture.rst => architecture/index.rst} (62%) delete mode 100644 docs/features/persistency/kvs/architecture/index.rst diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml rename to docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/architecture/_assets/kvs_interface.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml rename to docs/features/persistency/architecture/_assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/architecture/_assets/kvs_static_view.puml similarity index 100% rename from docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml rename to docs/features/persistency/architecture/_assets/kvs_static_view.puml diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/architecture/index.rst similarity index 62% rename from docs/features/persistency/kvs/architecture/feature_architecture.rst rename to docs/features/persistency/architecture/index.rst index 26718a6472..c8a73860c4 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/architecture/index.rst @@ -41,11 +41,11 @@ Static Architecture ------------------- .. feat_arc_sta:: Static Architecture - :id: feat_arc_sta__kvs__static + :id: feat_arc_sta__persistency__static :security: YES :safety: ASIL_B - :includes: logic_arc_int__kvs__interface - :fulfils: feat_req__kvs__default_value_retrieval,feat_req__kvs__default_values,feat_req__kvs__events,feat_req__kvs__integrity_check,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__stable_api,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values + :includes: logic_arc_int__persistency__interface + :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values :status: valid .. uml:: _assets/kvs_static_view.puml @@ -54,64 +54,64 @@ Dynamic Architecture -------------------- .. feat_arc_dyn:: Check if key contains default value - :id: feat_arc_dyn__kvs__check_key_default + :id: feat_arc_dyn__persistency__check_key_default :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :fulfils: feat_req__persistency__default_values,feat_req__persistency__default_value_get :status: valid .. uml:: _assets/kvs_dyn_check_value_default.puml .. feat_arc_dyn:: Delete key from KVS instance - :id: feat_arc_dyn__kvs__delete_key + :id: feat_arc_dyn__persistency__delete_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__events + :fulfils: feat_req__persistency__events :status: valid .. uml:: _assets/kvs_dyn_delete_data_key.puml .. feat_arc_dyn:: Flush to permanent storage - :id: feat_arc_dyn__kvs__flush + :id: feat_arc_dyn__persistency__flush :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__integrity_check,feat_req__persistency__snapshots :status: valid .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml .. feat_arc_dyn:: Read key value - :id: feat_arc_dyn__kvs__read_key + :id: feat_arc_dyn__persistency__read_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :fulfils: feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values,feat_req__persistency__default_values,feat_req__persistency__default_value_get :status: valid .. uml:: _assets/kvs_dyn_read_data_key.puml .. feat_arc_dyn:: Read data from permanent storage - :id: feat_arc_dyn__kvs__read_data_from_storage + :id: feat_arc_dyn__persistency__read_data_from_storage :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__snapshots :status: valid .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml .. feat_arc_dyn:: Write value to key - :id: feat_arc_dyn__kvs__write_key + :id: feat_arc_dyn__persistency__write_key :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values + :fulfils: feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values :status: valid .. uml:: _assets/kvs_dyn_write_data_key.puml .. feat_arc_dyn:: Restore snapshot - :id: feat_arc_dyn__kvs__snapshot_restore + :id: feat_arc_dyn__persistency__snapshot_restore :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency + :fulfils: feat_req__persistency__snapshots,feat_req__persistency__persist_data,feat_req__persistency__persistency :status: valid .. uml:: _assets/kvs_dyn_restore_snapshot.puml @@ -121,10 +121,10 @@ Logical Interfaces ------------------ .. logic_arc_int:: Ikvs - :id: logic_arc_int__kvs__interface + :id: logic_arc_int__persistency__interface :security: YES :safety: ASIL_B - :fulfils: feat_req__kvs__stable_api + :fulfils: feat_req__persistency__stable_api :status: valid .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index ac16cf0b2a..87bb7739c7 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -25,6 +25,7 @@ Key-Value-Storage :hidden: requirements/index.rst + architecture/index.rst Feature flag diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst deleted file mode 100644 index 335d087369..0000000000 --- a/docs/features/persistency/kvs/architecture/index.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Architecture -############# - -.. note:: - For now we store the component architecture in the feature tree, because multi-repo docs are not yet supported. - Once this support becomes available the component architecture will be moved to the module. - -.. toctree:: - :titlesonly: - - feature_architecture From 00943e8d51c53ad5a50de01250329af01e4a6e7a Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Fri, 9 May 2025 15:46:52 +0200 Subject: [PATCH 025/102] persistency_kvs: feature architecture Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../_assets/comp_dyn_kvs_key_get.puml | 36 +++++ .../architecture/_assets/kvs_dyn_builder.puml | 29 ++++ .../_assets/kvs_dyn_check_value_default.puml | 24 +++ .../_assets/kvs_dyn_delete_data_key.puml | 16 ++ .../kvs_dyn_flush_local_repr_to_file.puml | 60 ++++++++ .../_assets/kvs_dyn_read_data_key.puml | 20 +++ .../kvs_dyn_read_file_into_local_repr.puml | 49 ++++++ .../_assets/kvs_dyn_restore_snapshot.puml | 19 +++ .../_assets/kvs_dyn_write_data_key.puml | 11 ++ .../architecture/_assets/kvs_interface.puml | 23 +++ .../architecture/_assets/kvs_static_view.puml | 32 ++++ .../kvs/architecture/feature_architecture.rst | 139 ++++++++++++++++++ .../persistency/kvs/architecture/index.rst | 25 ++++ 13 files changed, 483 insertions(+) create mode 100644 docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml create mode 100644 docs/features/persistency/kvs/architecture/feature_architecture.rst create mode 100644 docs/features/persistency/kvs/architecture/index.rst diff --git a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml new file mode 100644 index 0000000000..d99890f239 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml @@ -0,0 +1,36 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +@startuml + +participant "Feature User" as actor +participant "«component» :Lower Level Component 1" as sc1 +participant "«component» :Lower Level Component 3" as sc3 + +actor -> sc1: real operation 3 () +sc1 -> sc3: real operation 9 () + +alt success + sc3 --> sc1: success +else error + sc3 --> sc1: error type +end + +alt success + sc1 --> actor: true +else error + sc1 -> actor: error type +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml new file mode 100644 index 0000000000..24bcfd97c6 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml @@ -0,0 +1,29 @@ +@startuml + +title Sequence Diagram: KVS Builder + +participant "User" as actor +participant "«component» :builder" as builder +participant "«component» :kvs" as kvs + +actor -> builder: Create KVS builder +builder --> actor: KVS builder instance + +actor -> builder: Set need_defaults flag +builder --> actor: KVS builder instance + +actor -> builder: Set need_kvs flag +builder --> actor: KVS builder instance + +actor -> builder: Build KVS instance +builder -> kvs: Open KVS with builder config + +alt kvs-open + kvs --> builder: KVS instance + builder --> actor: KVS instance +else kvs-open-error + kvs --> builder: KVS ErrorCode + builder --> actor: KVS ErrorCode +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml new file mode 100644 index 0000000000..b585fda342 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml @@ -0,0 +1,24 @@ +@startuml + +title Sequence Diagram: Check if Key contains Default Value + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Does key has default value + +alt default-key-exists + alt key-exists + alt default-and-key-match + kvs --> actor: Key contains default value + else key-doesnt-exist + kvs --> actor: Key doesn't containt default value + end + else key-doesnt-exist + kvs --> actor: Key contains default value + end +else default-doesnt-exist + kvs --> actor: Key doesn't contain default value +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml new file mode 100644 index 0000000000..e2b222e311 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml @@ -0,0 +1,16 @@ +@startuml + +title Sequence Diagram: Delete Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Remove key + +alt key-exists + kvs --> actor: Successfully deleted key +else key-doesnt-exist + kvs --> actor: Key-Not-Found-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml new file mode 100644 index 0000000000..c2150a6857 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml @@ -0,0 +1,60 @@ +@startuml + +title Sequence Diagram: Flush Local Representation to Data File + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :snapshot" as snapshot +participant "«component» :TinyJSON" as json_parser +participant "«component» :fs" as fs +participant "«component» :Adler32" as hasher + +actor -> kvs: Flush KVS + +kvs -> json_parser: Generate string from local representation + +alt json-string + json_parser --> kvs: JSON data string +else json-string-error + json_parser --> kvs: JSON generator error + kvs --> actor: JSON generator error +end + +kvs -> snapshot: Rotate snapshots + +alt snapshot-rotate + snapshot -> kvs: Snapshots rotated +else snapshot-rotate-error + snapshot --> kvs: Snapshot-Rotate-Error + kvs --> actor: Snapshot-Rotate-Error +end + +kvs -> hasher: Create JSON data string hash + +alt hash-created + hasher --> kvs: Data hash +else hash-create-error + hasher --> kvs: Hash-Calc-Error + kvs --> actor: Hash-Calc-Error +end + +kvs -> fs: Write JSON data string to file + +alt file-write + fs --> kvs: File successfully written +else file-write-error + fs --> kvs: File-Write-Error + kvs --> actor: File-Write-Error +end + +kvs -> fs: Write JSON data hash to file + +alt file-hash-write + fs --> kvs: Hash file successfully written + kvs --> actor: Flush successful +else file-hash-write-error + fs --> kvs: File-Hash-Write-Error + kvs --> actor: File-Hash-Write-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml new file mode 100644 index 0000000000..064e248911 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml @@ -0,0 +1,20 @@ +@startuml + +title Sequence Diagram: Read Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Get value for key + +alt key-exists + kvs --> actor: Return value for key +else key-doesnt-exist + alt default-exists + kvs --> actor: Return default value for key + else default-doesnt-exist + kvs --> actor: Key-Not-Found error + end +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml new file mode 100644 index 0000000000..c4cdbaffaa --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml @@ -0,0 +1,49 @@ +@startuml + +title Sequence Diagram: Read Data into Local Representation (KvsValue) + +participant "Builder" as actor +participant "«component» :kvs" as kvs +participant "«component» :TinyJSON" as json_parser +participant "«component» :fs" as fs +participant "«component» :Adler32" as hasher + +actor -> kvs: Open KVS + +kvs -> fs: Read defaults file + +alt file-exists + fs --> kvs: Defaults file content (JSON) +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> fs: Read defaults file hash + +alt file-exists + fs --> kvs: Defaults file hash +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> hasher: Generate defaults file hash +hasher --> kvs: Defaults file generated hash + +alt hash-matches + kvs -> json_parser: Parse JSON data +else hash-match-error + kvs -> actor: Hash-Error +end + +alt parsing-success + json_parser --> kvs: Parsed JSON object +else parsing-based-error + json_parser -> kvs: Parser-Error + kvs -> actor: Parser-Error +end + +kvs --> actor: KVS instance + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml new file mode 100644 index 0000000000..a18eab3b8a --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml @@ -0,0 +1,19 @@ +@startuml + +title Sequence Diagram: Restore Snapshot + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :snapshot" as snapshot + +actor -> kvs: Restore snapshot + +alt snapshot-found + snapshot --> kvs: Snapshot restored into local representation + kvs --> actor: Snapshot restored successfully +else snapshot-error + snapshot --> kvs: Snapshot-Not-Available-Error + kvs --> actor: Snapshot-Not-Available-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml new file mode 100644 index 0000000000..b34c24cc20 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml @@ -0,0 +1,11 @@ +@startuml + +title Sequence Diagram: Write Key to KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Set value for key +kvs --> actor: Value set for key + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml new file mode 100644 index 0000000000..e8e2e1750d --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml @@ -0,0 +1,23 @@ +@startuml + +interface Kvs { + open + flush_on_exit + reset + get_all_keys + key_exists + get_value + get_default_value + has_default_value + set_default_value + set_value + remove_key + flush + snapshot_count + snapshot_max_count + snapshot_restore + get_kvs_filename + get_hash_filename +} + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml new file mode 100644 index 0000000000..e016ae104a --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml @@ -0,0 +1,32 @@ +@startuml +allowmixing + +title Static View - kvs + +!include kvs_interface.puml + + +skinparam package { + BackgroundColor #E0E0D0 + BorderColor Black + backgroundColor<<feature>> yellow +} + +skinparam component { + backgroundColor<<component>> white +} + +' Define Features +package "kvs" <<feature>> { + component kvs <<component>> + component fs <<component>> + component tiny_json <<component>> +} + +kvs -u- Kvs + +kvs ..> tiny_json : use +kvs ..> fs : use + + +@enduml diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst new file mode 100644 index 0000000000..daad3c0b0c --- /dev/null +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -0,0 +1,139 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Architecture : persistency/kvs +==================================================== + +Overview +-------- + +- kvs provides the capability to efficiently store, retrieve, and + manage key-value pairs in a persistent storage system. + +Description +----------- + +- kvs organize data as pairs, where each unique key is associated with a specific value. + The key acts as a unique identifier for getting the value. +- The data is persisted in JSON format to the file system, providing a human-readable, + and widely supported way to store and manage key-value pairs. +- The JSON data persisted is according to RFC-8259. + +Rationale Behind Architecture Decomposition +******************************************* + +- The architecture is decomposed to include a dedicated JSON parser component (TinyJSON) to facilitate the persistent storage of data in JSON format. +- The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. + + +Static Architecture +------------------- + +.. feat_arc_sta:: Static Architecture + :id: feat_arc_sta__kvs__static + :security: YES + :safety: ASIL_B + :includes: feat_arc_int__kvs__interface + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_static_view.puml + +Dynamic Architecture +-------------------- + +.. feat_arc_dyn:: KVS Builder + :id: feat_arc_dyn__kvs__builder_pattern + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_dyn_builder.puml + +.. feat_arc_dyn:: Check if key contains default value + :id: feat_arc_dyn__kvs__check_key_default + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :status: valid + + .. uml:: _assets/kvs_dyn_check_value_default.puml + +.. feat_arc_dyn:: Delete key from KVS instance + :id: feat_arc_dyn__kvs__delete_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b + :status: valid + + .. uml:: _assets/kvs_dyn_delete_data_key.puml + +.. feat_arc_dyn:: Flush to permanent storage + :id: feat_arc_dyn__kvs__flush + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml + +.. feat_arc_dyn:: Read key value + :id: feat_arc_dyn__kvs__read_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval + :status: valid + + .. uml:: _assets/kvs_dyn_read_data_key.puml + +.. feat_arc_dyn:: Read data from permanent storage + :id: feat_arc_dyn__kvs__read_data_from_storage + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml + +.. feat_arc_dyn:: Write value to key + :id: feat_arc_dyn__kvs__write_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values + :status: valid + + .. uml:: _assets/kvs_dyn_write_data_key.puml + +.. feat_arc_dyn:: Restore snapshop + :id: feat_arc_dyn__kvs__snapshot_restore + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency + :status: valid + + .. uml:: _assets/kvs_dyn_restore_snapshot.puml + + +Logical Interfaces +------------------ + +.. feat_arc_int:: Ikvs + :id: feat_arc_int__kvs__interface + :security: YES + :safety: ASIL_B + :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__stable_api + :status: valid + + .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst new file mode 100644 index 0000000000..335d087369 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/index.rst @@ -0,0 +1,25 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Architecture +############# + +.. note:: + For now we store the component architecture in the feature tree, because multi-repo docs are not yet supported. + Once this support becomes available the component architecture will be moved to the module. + +.. toctree:: + :titlesonly: + + feature_architecture From 944b621d8b6fe234c8cb2cec8bd14c17c75b6d7d Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 14 May 2025 10:20:59 +0200 Subject: [PATCH 026/102] persistency_kvs: integrate review points from Volker See https://github.com/eclipse-score/score/pull/1068 Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/kvs/architecture/feature_architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index daad3c0b0c..90d0a2e6c3 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -13,7 +13,7 @@ # ******************************************************************************* Feature Architecture : persistency/kvs -==================================================== +====================================== Overview -------- From 682fd00e5d2a58413f7430c6e2dd304c55d664ba Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Tue, 20 May 2025 13:06:42 +0200 Subject: [PATCH 027/102] persistency_kvs: map all dynamic fulfilled feature reqs to static arch Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/kvs/architecture/feature_architecture.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst index 90d0a2e6c3..a4b54f5b8e 100644 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ b/docs/features/persistency/kvs/architecture/feature_architecture.rst @@ -44,8 +44,8 @@ Static Architecture :id: feat_arc_sta__kvs__static :security: YES :safety: ASIL_B - :includes: feat_arc_int__kvs__interface - :fulfils: feat_req__kvs__safety_asil_b + :includes: logic_arc_int__kvs__interface + :fulfils: feat_req__kvs__default_value_retrieval,feat_req__kvs__default_values,feat_req__kvs__events,feat_req__kvs__integrity_check,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__stable_api,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values :status: valid .. uml:: _assets/kvs_static_view.puml From f7554d70f902bb43379b7e90564d6694cc32b46b Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Fri, 9 May 2025 16:00:33 +0200 Subject: [PATCH 028/102] persistency_kvs: component requirements Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../requirements/component_requirements.rst | 190 ++++++++++++ .../requirements/feature_requirements.rst | 272 ++++++++++++++++++ .../persistency/requirements/index.rst | 8 + 3 files changed, 470 insertions(+) create mode 100644 docs/features/persistency/requirements/component_requirements.rst create mode 100644 docs/features/persistency/requirements/feature_requirements.rst diff --git a/docs/features/persistency/requirements/component_requirements.rst b/docs/features/persistency/requirements/component_requirements.rst new file mode 100644 index 0000000000..39f1d7ada7 --- /dev/null +++ b/docs/features/persistency/requirements/component_requirements.rst @@ -0,0 +1,190 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Component Requirements +###################### + +.. comp_req:: Key Handling + :id: comp_req__kvs__key_handling + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__supported_datatypes_keys + :status: valid + + The key must contain only alphanumerical characters, underscores and dashes. + The key must be valid UTF-8. + The key must be unique. + The key must have a maximum length of 32 bytes. + +.. comp_req:: Value Handling + :id: comp_req__kvs__value_handling + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values + :status: valid + + The value must have one of these datatypes: Number, String, Null, Array[Value], Dictionary{Key:Value}. + The value must be serializable and deserializable to JSON. + The value must have a maximum length of 1024 bytes. + The value can be no-set and provide a default value for this case. + If the value has a default value assigned it must be resetable to the default value. + +.. comp_req:: Default Value Handling + :id: comp_req__kvs__default_value_handling + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval,feat_req__kvs__default_value_reset,feat_req__kvs__default_value_file + :status: valid + + The default value can be available. + The default value must contain any of the valid value datatypes. + The default value must be retrieval through an extra API. + The default value must be configurable either in code or in a separate file. + If the default value is stored in a file the file must be secured by a checksum file. + +.. comp_req:: Constraint Configuration + :id: comp_req__kvs__constraints + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__config_file + :status: valid + + The KVS constraints must be configurable at compile-time + through source code constants or dynamically at runtime with a config file. + +.. comp_req:: Language Agnostic + :id: comp_req__kvs__language_agnostic + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__cpp_rust_interoperability + :status: valid + + The KVS must either provide an API that can be bind to other + languages or use a storage and memory exchange-format that can be adapted to + other languages. + +.. comp_req:: Concurrency + :id: comp_req__kvs__concurrency + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__intra_process_comm + :status: valid + + The KVS must implement thread-safe mechanisms to allow + concurrent access to the data without data races. + +.. comp_req:: Multi-Instance + :id: comp_req__kvs__multi_instance + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__multiple_kvs + :status: valid + + The KVS must manage all runtime variables in an instance so + that multiple instances with different KVS can be spawned and + used at the same time per software architecture element. + +.. comp_req:: Persistent Data Storage + :id: comp_req__kvs__persistent_data_storage + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__persist_data + :status: valid + + The KVS must use the file API and the JSON data format for + persistent data storage. + A checksum must be build over the data file and stored next to the data. + On data load the checksum must be verified. + +.. comp_req:: Persistent Data Schema Handling + :id: comp_req__kvs__persistent_data_schema + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__versioning,feat_req__kvs__update_mechanism + :status: valid + + The KVS doesn't support versioning directly. + The used JSON file storage format allows the application to implement + versioning, including up- and down-paths, by itself. + +.. comp_req:: Snapshots + :id: comp_req__kvs__snapshots + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__snapshots + :status: valid + + The KVS must write a snapshot whenever the data is stored. + It must maintain a configurable maximum number of snapshots. + Each new snapshot has id 1 and all older snapshots get their id increased.. + After the maximum snapshot number is reached the snapshots are rotated and the oldest snapshot is dropped. + Each snapshot can be restored by it's id. + Snapshots must be deletable. + +.. comp_req:: Develop Mode + :id: comp_req__kvs__dev_mode + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__dev_mode + :status: valid + + The KVS must provide a developer mode which can be enabled + during build time. This mode can be used to show debug and other internal + information. + +.. comp_req:: Async API + :id: comp_req__kvs__async_api + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__async_api + :status: valid + + Additional to the normal API the KVS must provide an Async + API. + +.. comp_req:: Permission Handling + :id: comp_req__kvs__permission_handling + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__kvs__access_control + :status: valid + + The KVS must not implement access and permission handling. + This is left to the underlying filesystem implementation. + The KVS must report access and permission errors that are + thrown by the filesystem to the application. + +.. comp_req:: Callback Support + :id: comp_req__kvs__callback_support + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__kvs__events + :status: valid + + The KVS must provide an API to register callbacks for + data-change events. diff --git a/docs/features/persistency/requirements/feature_requirements.rst b/docs/features/persistency/requirements/feature_requirements.rst new file mode 100644 index 0000000000..656c3e53a4 --- /dev/null +++ b/docs/features/persistency/requirements/feature_requirements.rst @@ -0,0 +1,272 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Requirements +#################### + +.. feat_req:: C++ & Rust Interoperability + :id: feat_req__kvs__cpp_rust_interoperability + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dev_experience__prog_languages + :status: valid + + The KVS system shall provide access through both C++ and Rust interfaces. + +.. feat_req:: Maximum Size + :id: feat_req__kvs__maximum_size + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: invalid + + The KVS system shall support specification of its maximum capacity at compile time. + +.. feat_req:: Multiple KVS per Software Architecture Element + :id: feat_req__kvs__multiple_kvs + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall allow instantiating multiple independent stores per software architecture element. + +.. feat_req:: Supported Datatypes (Keys) + :id: feat_req__kvs__supported_datatypes_keys + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support UTF-8 encoded strings as valid key types. + +.. feat_req:: Supported Datatypes (Values) + :id: feat_req__kvs__supported_datatypes_values + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support storing both primitive and non-primitive datatypes as values. + The supported datatypes shall match those used by the IPC feature. + +.. feat_req:: Default Values + :id: feat_req__kvs__default_values + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support predefined default values for keys. + +.. feat_req:: Default Value Retrieval + :id: feat_req__kvs__default_value_retrieval + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support retrieving the default value associated with a key. + +.. feat_req:: Default Value Reset + :id: feat_req__kvs__default_value_reset + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support resetting a single key or all keys to their respective default values. + +.. feat_req:: Persistency + :id: feat_req__kvs__persistency + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall persist stored data and provide an API to explicitly trigger persistence. + +.. feat_req:: Integrity Check + :id: feat_req__kvs__integrity_check + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall detect and report data corruption. + Note: Implementation depends on AoUs. + +.. feat_req:: Versioning + :id: feat_req__kvs__versioning + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support versioning for different layout configurations. + +.. feat_req:: Update Mechanism + :id: feat_req__kvs__update_mechanism + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall implement mechanisms to upgrade from one version to another, including multi-version jumps. + +.. feat_req:: Snapshots + :id: feat_req__kvs__snapshots + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall support explicit creation of snapshots identified by unique IDs and allow rollback to previous snapshots. + Snapshots shall also be deletable. + +.. feat_req:: Tooling + :id: feat_req__kvs__tooling + :reqtype: Non-Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__functiona_req__support_of_store + :status: valid + + The KVS system shall provide tooling support for viewing and modifying key-value pairs during development and debugging. + +.. feat_req:: Stable APIs + :id: feat_req__kvs__stable_api + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__communication__stable_app_inter + :status: valid + + The KVS API shall remain stable throughout its lifecycle while enabling the addition of new functionalities. + +.. feat_req:: Variant management support + :id: feat_req__kvs__variant_management + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__overall_goals__variant_management + :status: valid + + The KVS shall ensure compatibility across different architectures and versions. + +.. feat_req:: Set default key values via file + :id: feat_req__kvs__default_value_file + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + The KVS shall support the configuration of default key values using an external file. + +.. feat_req:: Configure limits via file + :id: feat_req__kvs__config_file + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + The KVS shall support the configuration of memory and other resource limits via a configuration file. + +.. feat_req:: Store persistent data + :id: feat_req__kvs__persist_data + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__data_persistency + :status: valid + + The KVS shall support storing and loading its data to and from persistent storage. + +.. feat_req:: Support engineering and field mode + :id: feat_req__kvs__dev_mode + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features + :status: valid + + The KVS shall provide both engineering (developer) and field modes. + The engineering mode shall allow unrestricted data access. + +.. feat_req:: Provide an async API + :id: feat_req__kvs__async_api + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dependability__availability, stkh_req__app_architectures__support_request + :status: valid + + The KVS shall provide an asynchronous API for accessing and manipulating data. + +.. feat_req:: Separate data stores + :id: feat_req__kvs__access_control + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__dependability__security_features + :status: valid + + The KVS shall ensure that only authorized components can access individual data stores. + +.. feat_req:: Data-change events + :id: feat_req__kvs__events + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__app_architectures__support_data + :status: valid + + The KVS shall provide an API that allows for the registration of callback + functions. These callbacks shall be invoked in response to specific events, + such as when keys are changed or removed. + +.. feat_req:: Fast access + :id: feat_req__kvs__fast_access + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__short_app_cycles + :status: valid + + The KVS shall ensure that key operations are typically completed within 5 milliseconds. + +.. feat_req:: Intra-Process Data Access + :id: feat_req__kvs__intra_process_comm + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__communication__intra_process + :status: valid + + The KVS shall support concurrent intra-process data access. diff --git a/docs/features/persistency/requirements/index.rst b/docs/features/persistency/requirements/index.rst index a9cf044a00..323ef780cc 100644 --- a/docs/features/persistency/requirements/index.rst +++ b/docs/features/persistency/requirements/index.rst @@ -15,6 +15,7 @@ Requirements ############ +<<<<<<< HEAD:docs/features/persistency/requirements/index.rst .. feat_req:: C++ & Rust Interoperability :id: feat_req__persistency__cpp_rust_interop :reqtype: Non-Functional @@ -270,3 +271,10 @@ Requirements :status: valid The KVS shall support concurrent intra-process data access. +======= +.. toctree:: + :titlesonly: + + feature_requirements + component_requirements +>>>>>>> 13a7ca4ac (persistency_kvs: component requirements):docs/features/persistency/kvs/requirements/index.rst From cbeaa3b652e95ef310efadd91113214a891ba55f Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Thu, 22 May 2025 13:06:32 +0200 Subject: [PATCH 029/102] persistency_kvs: reword component req after IREB standard Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../requirements/component_requirements.rst | 82 ++++++++----------- 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/docs/features/persistency/requirements/component_requirements.rst b/docs/features/persistency/requirements/component_requirements.rst index 39f1d7ada7..24c92e0109 100644 --- a/docs/features/persistency/requirements/component_requirements.rst +++ b/docs/features/persistency/requirements/component_requirements.rst @@ -23,10 +23,10 @@ Component Requirements :satisfies: feat_req__kvs__supported_datatypes_keys :status: valid - The key must contain only alphanumerical characters, underscores and dashes. - The key must be valid UTF-8. - The key must be unique. - The key must have a maximum length of 32 bytes. + The system shall ensure that each key consists solely of alphanumeric characters, underscores, or dashes. + The system shall ensure that each key is encoded as valid UTF-8. + The system shall guarantee the uniqueness of each key. + The system shall limit the maximum length of a key to 32 bytes. .. comp_req:: Value Handling :id: comp_req__kvs__value_handling @@ -36,11 +36,11 @@ Component Requirements :satisfies: feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values :status: valid - The value must have one of these datatypes: Number, String, Null, Array[Value], Dictionary{Key:Value}. - The value must be serializable and deserializable to JSON. - The value must have a maximum length of 1024 bytes. - The value can be no-set and provide a default value for this case. - If the value has a default value assigned it must be resetable to the default value. + The system shall only accept values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. + The system shall ensure that all values can be serialized to and deserialized from JSON. + The system shall restrict the maximum length of a value to 1024 bytes. + The system shall support unset values and provide a default value in such cases. + The system shall ensure that, if a value has a default, it is possible to reset the value to its default. .. comp_req:: Default Value Handling :id: comp_req__kvs__default_value_handling @@ -50,11 +50,11 @@ Component Requirements :satisfies: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval,feat_req__kvs__default_value_reset,feat_req__kvs__default_value_file :status: valid - The default value can be available. - The default value must contain any of the valid value datatypes. - The default value must be retrieval through an extra API. - The default value must be configurable either in code or in a separate file. - If the default value is stored in a file the file must be secured by a checksum file. + The system may provide default values. + The system shall ensure that each default value is of a permitted value data type. + The system shall provide an additional API to retrieve default values. + The system shall allow configuration of default values either in code or in a separate configuration file. + The system shall, if default values are stored in a file, secure this file with an associated checksum file. .. comp_req:: Constraint Configuration :id: comp_req__kvs__constraints @@ -64,8 +64,7 @@ Component Requirements :satisfies: feat_req__kvs__config_file :status: valid - The KVS constraints must be configurable at compile-time - through source code constants or dynamically at runtime with a config file. + The system shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. .. comp_req:: Language Agnostic :id: comp_req__kvs__language_agnostic @@ -75,9 +74,7 @@ Component Requirements :satisfies: feat_req__kvs__cpp_rust_interoperability :status: valid - The KVS must either provide an API that can be bind to other - languages or use a storage and memory exchange-format that can be adapted to - other languages. + The system shall either provide an API that supports bindings to other languages or use a storage and memory exchange format that is adaptable to other languages. .. comp_req:: Concurrency :id: comp_req__kvs__concurrency @@ -87,8 +84,7 @@ Component Requirements :satisfies: feat_req__kvs__intra_process_comm :status: valid - The KVS must implement thread-safe mechanisms to allow - concurrent access to the data without data races. + The system shall implement thread-safe mechanisms to enable concurrent access to data without data races. .. comp_req:: Multi-Instance :id: comp_req__kvs__multi_instance @@ -98,9 +94,7 @@ Component Requirements :satisfies: feat_req__kvs__multiple_kvs :status: valid - The KVS must manage all runtime variables in an instance so - that multiple instances with different KVS can be spawned and - used at the same time per software architecture element. + The system shall manage all runtime variables within an instance, such that multiple KVS instances can be created and used concurrently within a single software architecture element. .. comp_req:: Persistent Data Storage :id: comp_req__kvs__persistent_data_storage @@ -110,10 +104,9 @@ Component Requirements :satisfies: feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__persist_data :status: valid - The KVS must use the file API and the JSON data format for - persistent data storage. - A checksum must be build over the data file and stored next to the data. - On data load the checksum must be verified. + The system shall use the file API and the JSON data format to persist data. + The system shall generate a checksum for each data file and store it alongside the data. + The system shall verify the checksum upon loading data. .. comp_req:: Persistent Data Schema Handling :id: comp_req__kvs__persistent_data_schema @@ -123,9 +116,8 @@ Component Requirements :satisfies: feat_req__kvs__versioning,feat_req__kvs__update_mechanism :status: valid - The KVS doesn't support versioning directly. - The used JSON file storage format allows the application to implement - versioning, including up- and down-paths, by itself. + The system shall not provide built-in versioning. + The chosen JSON file storage format shall enable the application to implement versioning, including upgrade and downgrade paths, as needed. .. comp_req:: Snapshots :id: comp_req__kvs__snapshots @@ -135,12 +127,12 @@ Component Requirements :satisfies: feat_req__kvs__snapshots :status: valid - The KVS must write a snapshot whenever the data is stored. - It must maintain a configurable maximum number of snapshots. - Each new snapshot has id 1 and all older snapshots get their id increased.. - After the maximum snapshot number is reached the snapshots are rotated and the oldest snapshot is dropped. - Each snapshot can be restored by it's id. - Snapshots must be deletable. + The system shall create a snapshot each time data is stored. + The system shall maintain a configurable maximum number of snapshots. + The system shall assign the ID 1 to the newest snapshot and increment the IDs of older snapshots accordingly. + The system shall rotate and delete the oldest snapshot when the maximum number is reached. + The system shall allow restoration of a snapshot by its ID. + The system shall allow deletion of individual snapshots. .. comp_req:: Develop Mode :id: comp_req__kvs__dev_mode @@ -150,9 +142,7 @@ Component Requirements :satisfies: feat_req__kvs__dev_mode :status: valid - The KVS must provide a developer mode which can be enabled - during build time. This mode can be used to show debug and other internal - information. + The system shall provide a developer mode that can be enabled during build time to display debugging and internal information. .. comp_req:: Async API :id: comp_req__kvs__async_api @@ -162,8 +152,7 @@ Component Requirements :satisfies: feat_req__kvs__async_api :status: valid - Additional to the normal API the KVS must provide an Async - API. + The system shall provide, in addition to the standard API, an asynchronous API. .. comp_req:: Permission Handling :id: comp_req__kvs__permission_handling @@ -173,10 +162,8 @@ Component Requirements :satisfies: feat_req__kvs__access_control :status: valid - The KVS must not implement access and permission handling. - This is left to the underlying filesystem implementation. - The KVS must report access and permission errors that are - thrown by the filesystem to the application. + The system shall not implement its own access or permission controls but shall rely on the underlying filesystem for permission management. + The system shall report any access or permission errors encountered at the filesystem level to the application. .. comp_req:: Callback Support :id: comp_req__kvs__callback_support @@ -186,5 +173,4 @@ Component Requirements :satisfies: feat_req__kvs__events :status: valid - The KVS must provide an API to register callbacks for - data-change events. + The system shall provide an API for registering callbacks that are triggered by data change events. From 84e7041b099fbe69d4d66062a0bccb589880dd84 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Thu, 22 May 2025 13:23:06 +0200 Subject: [PATCH 030/102] persistency_kvs: reword component reqs to match the template https://eclipse-score.github.io/score/pr-1069/process/process_areas/requirements_engineering/guidance/requirements_templates.html#gd_temp__req__formulation Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../requirements/component_requirements.rst | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/docs/features/persistency/requirements/component_requirements.rst b/docs/features/persistency/requirements/component_requirements.rst index 24c92e0109..12180dc6a8 100644 --- a/docs/features/persistency/requirements/component_requirements.rst +++ b/docs/features/persistency/requirements/component_requirements.rst @@ -23,10 +23,10 @@ Component Requirements :satisfies: feat_req__kvs__supported_datatypes_keys :status: valid - The system shall ensure that each key consists solely of alphanumeric characters, underscores, or dashes. - The system shall ensure that each key is encoded as valid UTF-8. - The system shall guarantee the uniqueness of each key. - The system shall limit the maximum length of a key to 32 bytes. + The component shall accept keys that consist solely of alphanumeric characters, underscores, or dashes. + The component shall encode each key as valid UTF-8. + The component shall guarantee that each key is unique. + The component shall limit the maximum length of a key to 32 bytes. .. comp_req:: Value Handling :id: comp_req__kvs__value_handling @@ -36,11 +36,11 @@ Component Requirements :satisfies: feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values :status: valid - The system shall only accept values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. - The system shall ensure that all values can be serialized to and deserialized from JSON. - The system shall restrict the maximum length of a value to 1024 bytes. - The system shall support unset values and provide a default value in such cases. - The system shall ensure that, if a value has a default, it is possible to reset the value to its default. + The component shall accept only values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. + The component shall serialize and deserialize all values to and from JSON. + The component shall limit the maximum length of a value to 1024 bytes. + The component shall support unset values and shall provide a default value when a value is unset. + The component shall allow resetting a value to its default if a default is defined. .. comp_req:: Default Value Handling :id: comp_req__kvs__default_value_handling @@ -50,11 +50,10 @@ Component Requirements :satisfies: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval,feat_req__kvs__default_value_reset,feat_req__kvs__default_value_file :status: valid - The system may provide default values. - The system shall ensure that each default value is of a permitted value data type. - The system shall provide an additional API to retrieve default values. - The system shall allow configuration of default values either in code or in a separate configuration file. - The system shall, if default values are stored in a file, secure this file with an associated checksum file. + The component shall accept default values of only permitted value data types. + The component shall provide an API to retrieve default values. + The component shall allow configuration of default values in code or in a separate configuration file. + The component shall secure the configuration file for default values with an associated checksum file when default values are stored in a file. .. comp_req:: Constraint Configuration :id: comp_req__kvs__constraints @@ -64,7 +63,7 @@ Component Requirements :satisfies: feat_req__kvs__config_file :status: valid - The system shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. + The component shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. .. comp_req:: Language Agnostic :id: comp_req__kvs__language_agnostic @@ -74,7 +73,7 @@ Component Requirements :satisfies: feat_req__kvs__cpp_rust_interoperability :status: valid - The system shall either provide an API that supports bindings to other languages or use a storage and memory exchange format that is adaptable to other languages. + The component shall provide an API that supports bindings to other languages or shall use a storage and memory exchange format that is adaptable to other languages. .. comp_req:: Concurrency :id: comp_req__kvs__concurrency @@ -84,7 +83,7 @@ Component Requirements :satisfies: feat_req__kvs__intra_process_comm :status: valid - The system shall implement thread-safe mechanisms to enable concurrent access to data without data races. + The component shall implement thread-safe mechanisms to enable concurrent access to data without data races. .. comp_req:: Multi-Instance :id: comp_req__kvs__multi_instance @@ -94,7 +93,7 @@ Component Requirements :satisfies: feat_req__kvs__multiple_kvs :status: valid - The system shall manage all runtime variables within an instance, such that multiple KVS instances can be created and used concurrently within a single software architecture element. + The component shall manage all runtime variables within an instance to enable creation and use of multiple KVS instances concurrently within a single software architecture element. .. comp_req:: Persistent Data Storage :id: comp_req__kvs__persistent_data_storage @@ -104,9 +103,9 @@ Component Requirements :satisfies: feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__persist_data :status: valid - The system shall use the file API and the JSON data format to persist data. - The system shall generate a checksum for each data file and store it alongside the data. - The system shall verify the checksum upon loading data. + The component shall use the file API and the JSON data format to persist data. + The component shall generate a checksum for each data file and shall store it alongside the data. + The component shall verify the checksum when loading data. .. comp_req:: Persistent Data Schema Handling :id: comp_req__kvs__persistent_data_schema @@ -116,8 +115,8 @@ Component Requirements :satisfies: feat_req__kvs__versioning,feat_req__kvs__update_mechanism :status: valid - The system shall not provide built-in versioning. - The chosen JSON file storage format shall enable the application to implement versioning, including upgrade and downgrade paths, as needed. + The component shall not provide built-in versioning. + The component shall use a JSON file storage format that enables the application to implement versioning, including upgrade and downgrade paths, as needed. .. comp_req:: Snapshots :id: comp_req__kvs__snapshots @@ -127,12 +126,12 @@ Component Requirements :satisfies: feat_req__kvs__snapshots :status: valid - The system shall create a snapshot each time data is stored. - The system shall maintain a configurable maximum number of snapshots. - The system shall assign the ID 1 to the newest snapshot and increment the IDs of older snapshots accordingly. - The system shall rotate and delete the oldest snapshot when the maximum number is reached. - The system shall allow restoration of a snapshot by its ID. - The system shall allow deletion of individual snapshots. + The component shall create a snapshot each time data is stored. + The component shall maintain a configurable maximum number of snapshots. + The component shall assign the ID 1 to the newest snapshot and shall increment the IDs of older snapshots accordingly. + The component shall rotate and delete the oldest snapshot when the maximum number is reached. + The component shall allow restoration of a snapshot by its ID. + The component shall allow deletion of individual snapshots. .. comp_req:: Develop Mode :id: comp_req__kvs__dev_mode @@ -142,7 +141,7 @@ Component Requirements :satisfies: feat_req__kvs__dev_mode :status: valid - The system shall provide a developer mode that can be enabled during build time to display debugging and internal information. + The component shall provide a developer mode that can be enabled during build time to display debugging and internal information. .. comp_req:: Async API :id: comp_req__kvs__async_api @@ -152,7 +151,7 @@ Component Requirements :satisfies: feat_req__kvs__async_api :status: valid - The system shall provide, in addition to the standard API, an asynchronous API. + The component shall provide an asynchronous API in addition to the standard API. .. comp_req:: Permission Handling :id: comp_req__kvs__permission_handling @@ -162,8 +161,8 @@ Component Requirements :satisfies: feat_req__kvs__access_control :status: valid - The system shall not implement its own access or permission controls but shall rely on the underlying filesystem for permission management. - The system shall report any access or permission errors encountered at the filesystem level to the application. + The component shall rely on the underlying filesystem for access and permission management and shall not implement its own access or permission controls. + The component shall report any access or permission errors encountered at the filesystem level to the application. .. comp_req:: Callback Support :id: comp_req__kvs__callback_support @@ -173,4 +172,4 @@ Component Requirements :satisfies: feat_req__kvs__events :status: valid - The system shall provide an API for registering callbacks that are triggered by data change events. + The component shall provide an API for registering callbacks that are triggered by data change events. From 69dcd8d2eb3186e13ba423b5def4574a48fada05 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 4 Jun 2025 13:45:37 +0200 Subject: [PATCH 031/102] persistency_kvs: move KVS to new directory structure Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- docs/contribute/general/naming.rst | 2 +- .../feature_name/safety_analysis/dfa.rst | 76 +- .../feature_name/safety_analysis/fmea.rst | 32 +- .../persistency/architecture/index.rst | 3 +- docs/features/persistency/index.rst | 76 +- .../_assets/comp_dyn_kvs_key_get.puml | 36 - .../architecture/_assets/kvs_dyn_builder.puml | 29 - .../_assets/kvs_dyn_check_value_default.puml | 24 - .../_assets/kvs_dyn_delete_data_key.puml | 16 - .../kvs_dyn_flush_local_repr_to_file.puml | 60 -- .../_assets/kvs_dyn_read_data_key.puml | 20 - .../kvs_dyn_read_file_into_local_repr.puml | 49 - .../_assets/kvs_dyn_restore_snapshot.puml | 19 - .../_assets/kvs_dyn_write_data_key.puml | 11 - .../architecture/_assets/kvs_interface.puml | 23 - .../architecture/_assets/kvs_static_view.puml | 32 - .../kvs/architecture/feature_architecture.rst | 139 --- .../persistency/kvs/architecture/index.rst | 25 - .../requirements/component_requirements.rst | 175 ---- .../requirements/feature_requirements.rst | 272 ------ .../persistency/requirements/index.rst | 8 - .../persistency/safety_analysis/dfa.rst | 868 ++++++++++++++++++ .../persistency/safety_analysis/fmea.rst | 393 ++++++++ .../persistency/safety_planning/index.rst | 130 +++ .../kvs/docs/requirements/index.rst | 191 +++- 25 files changed, 1624 insertions(+), 1085 deletions(-) delete mode 100644 docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml delete mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml delete mode 100644 docs/features/persistency/kvs/architecture/feature_architecture.rst delete mode 100644 docs/features/persistency/kvs/architecture/index.rst delete mode 100644 docs/features/persistency/requirements/component_requirements.rst delete mode 100644 docs/features/persistency/requirements/feature_requirements.rst create mode 100644 docs/features/persistency/safety_analysis/dfa.rst create mode 100644 docs/features/persistency/safety_analysis/fmea.rst create mode 100644 docs/features/persistency/safety_planning/index.rst diff --git a/docs/contribute/general/naming.rst b/docs/contribute/general/naming.rst index eef6a53b2b..16c97d61fe 100644 --- a/docs/contribute/general/naming.rst +++ b/docs/contribute/general/naming.rst @@ -54,7 +54,7 @@ For the naming of the UIDs also following convention shall be applied: As examples: * feat_req__ipc__e2e_protection -* comp_req__kvs__storage +* comp_req__persistency__storage Only for **process UIDs** the structural element is optional: diff --git a/docs/features/feature_name/safety_analysis/dfa.rst b/docs/features/feature_name/safety_analysis/dfa.rst index d3e9f3bda0..8aed7eed32 100644 --- a/docs/features/feature_name/safety_analysis/dfa.rst +++ b/docs/features/feature_name/safety_analysis/dfa.rst @@ -22,7 +22,7 @@ Persistency DFA :tags: feature_persistency | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_01 | :violation_cause: Reused software module. N/A @@ -34,7 +34,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_02 | :violation_cause: Libraries. . N/A @@ -46,7 +46,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_04 | :violation_cause: Basic software. N/A @@ -58,7 +58,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_05 | :violation_cause: Operating system including scheduler. Platformebene. Nicht von Middleware handlebar @@ -70,7 +70,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_06 | :violation_cause: Any service stack, e.g. communication stack. N/A @@ -82,11 +82,11 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_07 | :violation_cause: Configuration data. Return values might be falsified. - | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__kvs__integrity_check + | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__persistency__integrity_check | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> | :mitigation_coverage: <0..100%> | :sufficient: <yes|no> @@ -94,7 +94,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_09 | :violation_cause: Execution time. N/A @@ -106,7 +106,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SR_01_10 | :violation_cause: Allocated memory. Diskussion aktuell in Feature-Community. JSON kann das, sollte aber eigentlich nicht erlaubt sein @@ -118,7 +118,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_01 | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) <- Checken ob das Fehlerbild überhaupt passt. 1. Satzteil nicht passen zu 2.> @@ -130,11 +130,11 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_02 | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information. Fehlerhafte ausführung oder nichtverfügbarkeit vom feature - | :mitigation: < NONE|ID from Feature Requirement> feat_req__kvs__integrity_check + | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> | :mitigation_coverage: <0..100%> | :sufficient: <yes|no> @@ -142,11 +142,11 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_03 | :violation_cause: Insertion / sequence of information wie CO_01_02 - | :mitigation: < NONE|ID from Feature Requirement> feat_req__kvs__integrity_check + | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> | :mitigation_coverage: <0..100%> | :sufficient: <yes|no> @@ -154,7 +154,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_04 | :violation_cause: Corruption of information, inconsistent data wie CO_01_02 @@ -166,7 +166,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_05 | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations N/A @@ -178,7 +178,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_06 | :violation_cause: Information from a sender received by only a subset of the receivers. N/A @@ -190,7 +190,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: CO_01_07 | :violation_cause: Blocking access to a communication channel N/A @@ -202,7 +202,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SI_01_02 | :violation_cause: Configuration data. N/A @@ -214,7 +214,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SI_01_03 | :violation_cause: Constants, or variables, being global to the two software functions. N/A @@ -226,7 +226,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SI_01_04 | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions. N/A @@ -238,7 +238,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SI_01_05 | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function. Unklar was das Fehlerbild ist @@ -250,7 +250,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_01 | :violation_cause: Memory miss-allocation and leaks. Platformebene @@ -262,7 +262,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_02 | :violation_cause: Read/Write access to memory allocated to another software element. Platformebene @@ -274,7 +274,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_03 | :violation_cause: Stack/Buffer under-/overflow. Könnte passieren, ist aber unwahrscheinlich in RUST. Recursive Funktionen könnten die Ursache sein. @@ -286,7 +286,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_04 | :violation_cause: Deadlocks. Könnten auftreten. Würde von Applikation verursacht werden. KVS kann da nichts machen @@ -298,7 +298,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_05 | :violation_cause: Livelocks wie UI_01_04 @@ -310,7 +310,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_06 | :violation_cause: Blocking of execution. Feature is not available. @@ -322,7 +322,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_07 | :violation_cause: Incorrect allocation of execution time. N/A @@ -334,7 +334,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_08 | :violation_cause: Incorrect execution flow N/A @@ -346,7 +346,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_09 | :violation_cause: Incorrect synchronization between software elements N/A @@ -358,7 +358,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_10 | :violation_cause: CPU time depletion N/A @@ -370,7 +370,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_11 | :violation_cause: Memory depletion N/A @@ -382,7 +382,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: UI_01_12 | :violation_cause: Other HW unavailability N/A @@ -394,7 +394,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SC_01_02 | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) @@ -406,7 +406,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SC_01_03 | :violation_cause: Same personal @@ -418,7 +418,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SC_01_04 | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. @@ -430,7 +430,7 @@ Persistency DFA | :status: <valid|invalid> | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__kvs__check_key_default + | :verifies: feat_arc_dyn__persistency__check_key_default | :id: feat_saf_DFA__persistency__check_key_default | :violation_id: SC_01_05 | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. diff --git a/docs/features/feature_name/safety_analysis/fmea.rst b/docs/features/feature_name/safety_analysis/fmea.rst index ec2affc54f..7097c89ac2 100644 --- a/docs/features/feature_name/safety_analysis/fmea.rst +++ b/docs/features/feature_name/safety_analysis/fmea.rst @@ -22,7 +22,7 @@ Persistency Safety Analysis :tags: feature_persistency | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_01 | :failure_effect: Message is not received. User is not able to use the feature. Middleware cant be used.A @@ -34,7 +34,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_02 | :failure_effect: message received too late. User might not able to use the feature. Middleware cant be used. @@ -46,7 +46,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_03 | :failure_effect: message received too early. No impact / feature reacts only if triggered on the trigger. @@ -58,7 +58,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_04 | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost). N/A @@ -70,7 +70,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_05 | :failure_effect: message is corrupted. Covered by MF_01_01 @@ -82,7 +82,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_06 | :failure_effect: message is not sent. Covered by MF_01_01 @@ -94,7 +94,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: MF_01_07 | :failure_effect: message is unintended sent. Covered by MF_01_01 @@ -106,7 +106,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: CO_01_01 | :failure_effect: minimum constraint boundary is violated. N/A @@ -118,7 +118,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: CO_01_02 | :failure_effect: maximum constraint boundary is violated. N/A @@ -130,7 +130,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_01 | :failure_effect: Process calculates wrong result(s). Feature is not usable. @@ -142,7 +142,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_02 | :failure_effect: processing too slow. N/A @@ -154,7 +154,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_03 | :failure_effect: processing too fast. N/A @@ -166,7 +166,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_04 | :failure_effect: loss of execution. User is not able to use the feature. Middleware cant be used. @@ -178,7 +178,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_05 | :failure_effect: processing changes to arbitrary process. N/A @@ -190,7 +190,7 @@ Persistency Safety Analysis | :status: <valid|invalid> | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__kvs__static + | :verifies: feat_arc_sta__persistency__static | :id: feat_saf_FMEA__persistency__open_KVS | :failure_mode: EX_01_06 | :failure_effect: processing is not complete (infinite loop). User is not able to use the feature. Middleware cant be used. @@ -390,4 +390,4 @@ Persistency Safety Analysis | :mitigation_coverage: <0..100%> | :sufficient: <yes|no> | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> \ No newline at end of file + | :status: <valid|invalid> diff --git a/docs/features/persistency/architecture/index.rst b/docs/features/persistency/architecture/index.rst index c8a73860c4..a56e5daf3b 100644 --- a/docs/features/persistency/architecture/index.rst +++ b/docs/features/persistency/architecture/index.rst @@ -52,7 +52,6 @@ Static Architecture Dynamic Architecture -------------------- - .. feat_arc_dyn:: Check if key contains default value :id: feat_arc_dyn__persistency__check_key_default :security: YES @@ -90,7 +89,7 @@ Dynamic Architecture .. uml:: _assets/kvs_dyn_read_data_key.puml .. feat_arc_dyn:: Read data from permanent storage - :id: feat_arc_dyn__persistency__read_data_from_storage + :id: feat_arc_dyn__persistency__read_from_storage :security: YES :safety: ASIL_B :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__snapshots diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index 87bb7739c7..76e8ac97a6 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -19,13 +19,11 @@ Key-Value-Storage :id: doc__persistency_kvs :status: draft :safety: ASIL_B - :tags: contribution_request, feature_request + :tags: feature_request, persistency_kvs .. toctree:: - :hidden: - - requirements/index.rst architecture/index.rst + requirements/index.rst Feature flag @@ -68,36 +66,18 @@ platform. Rationale ========= -1. There are multiple key-value storages allowed per application. - -To allow for data separation and different levels of security, each application -is allowed to have multiple KVS. - -2. There must be an update mechanism from different versions of a KVS to another version. - -Staying compatible through updates and rollbacks is a main requirement for the -project. - -3. The same KVS should be read/writable from C++ & Rust and any other language. - -Having a flexible interface allows to focus on solutions where the language -fits the needs. - -4. KVS should store default values. - -If possible, all keys should return a configurable default value or the access -should return an error if the key needs to be written first. - -5. KVS should use a simple data representation. - -The KVS should use a data representation that supports versioned up- and -downgrading like JSON or Cap'n Proto and is easily debuggable by the developer. - -6. Integrity of the KVS should be checked. - -The KVS is always be in a consistent state that either provides the currently -stored data or if not possible the previous snapshot. - +1. | Requirement 1: Multiple key-value storages per application + | Solution: Allow each application to have multiple key-value storages (KVS) to enable data separation and different levels of security. +2. | Requirement 2: Update mechanism for KVS versions + | Solution: Implement an update mechanism to ensure compatibility through updates and rollbacks of different KVS versions. +3. | Requirement 3: Language-agnostic KVS interface + | Solution: Design a flexible interface that allows the KVS to be read and written from multiple programming languages, including C++, Rust, and others. +4. | Requirement 4: Default values for KVS + | Solution: Configure the KVS to store default values for all keys, returning either the default value or an error if the key needs to be written first. +5. | Requirement 5: Simple data representation for KVS + | Solution: Utilize a simple data representation, such as JSON or Cap'n Proto, that supports versioned up- and downgrading and is easily debuggable by developers. +6. | Requirement 6: KVS integrity checking + | Solution: Ensure the KVS maintains a consistent state, providing either the currently stored data or the previous snapshot if data retrieval is not possible. Backwards Compatibility ======================= @@ -113,27 +93,31 @@ Security Impact =============== Access to the key-value-storage would allow a malicious user to control the -behaviour of the device so it needs to be secured as much as possible, like -only providing debug access when a debug firmware image is installed. +behaviour of the device, so it must be secured to prevent unauthorized access. +To achieve this, debug access should only be provided when a debug firmware +image is installed. Safety Impact ============= - .. note:: - One key-value storage should not be used within different processes (freedom from interference) -> To be added to AoUs? +The expected ASIL level is ASIL-B. To reach this goal we will apply the S-CORE +development process. Key elements of it are listed in the process descriptions +of safety management and safety analysis. In the safety analysis we will +analyze the impact of the feature. -[How could the safety be impacted by the new feature?] + .. note:: + TODO: Link to safety analysis. - .. note:: - If there are safety concerns in relation to the Feature Request, those concerns should be explicitly written out to make sure reviewers of the Feature Request are aware of them. - ToDo - Link to the Safety Impact Method +We use an iterative development process and apply results from the next steps +back to the feature request. For TinyJSON we will perform a software component +classification. -[What is the expected ASIL level?] -[What is the expected classification of the contribution?] + .. note:: + TODO: Link to component classification. - .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: (TODO: add link to component classification). +To ensure the freedom of interference the feature key-value storage should not +be used within different processes. License Impact diff --git a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml b/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml deleted file mode 100644 index d99890f239..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/comp_dyn_kvs_key_get.puml +++ /dev/null @@ -1,36 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -@startuml - -participant "Feature User" as actor -participant "«component» :Lower Level Component 1" as sc1 -participant "«component» :Lower Level Component 3" as sc3 - -actor -> sc1: real operation 3 () -sc1 -> sc3: real operation 9 () - -alt success - sc3 --> sc1: success -else error - sc3 --> sc1: error type -end - -alt success - sc1 --> actor: true -else error - sc1 -> actor: error type -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml deleted file mode 100644 index 24bcfd97c6..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml +++ /dev/null @@ -1,29 +0,0 @@ -@startuml - -title Sequence Diagram: KVS Builder - -participant "User" as actor -participant "«component» :builder" as builder -participant "«component» :kvs" as kvs - -actor -> builder: Create KVS builder -builder --> actor: KVS builder instance - -actor -> builder: Set need_defaults flag -builder --> actor: KVS builder instance - -actor -> builder: Set need_kvs flag -builder --> actor: KVS builder instance - -actor -> builder: Build KVS instance -builder -> kvs: Open KVS with builder config - -alt kvs-open - kvs --> builder: KVS instance - builder --> actor: KVS instance -else kvs-open-error - kvs --> builder: KVS ErrorCode - builder --> actor: KVS ErrorCode -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml deleted file mode 100644 index b585fda342..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml - -title Sequence Diagram: Check if Key contains Default Value - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Does key has default value - -alt default-key-exists - alt key-exists - alt default-and-key-match - kvs --> actor: Key contains default value - else key-doesnt-exist - kvs --> actor: Key doesn't containt default value - end - else key-doesnt-exist - kvs --> actor: Key contains default value - end -else default-doesnt-exist - kvs --> actor: Key doesn't contain default value -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml deleted file mode 100644 index e2b222e311..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml +++ /dev/null @@ -1,16 +0,0 @@ -@startuml - -title Sequence Diagram: Delete Key from KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Remove key - -alt key-exists - kvs --> actor: Successfully deleted key -else key-doesnt-exist - kvs --> actor: Key-Not-Found-Error -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml deleted file mode 100644 index c2150a6857..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml +++ /dev/null @@ -1,60 +0,0 @@ -@startuml - -title Sequence Diagram: Flush Local Representation to Data File - -participant "User" as actor -participant "«component» :kvs" as kvs -participant "«component» :snapshot" as snapshot -participant "«component» :TinyJSON" as json_parser -participant "«component» :fs" as fs -participant "«component» :Adler32" as hasher - -actor -> kvs: Flush KVS - -kvs -> json_parser: Generate string from local representation - -alt json-string - json_parser --> kvs: JSON data string -else json-string-error - json_parser --> kvs: JSON generator error - kvs --> actor: JSON generator error -end - -kvs -> snapshot: Rotate snapshots - -alt snapshot-rotate - snapshot -> kvs: Snapshots rotated -else snapshot-rotate-error - snapshot --> kvs: Snapshot-Rotate-Error - kvs --> actor: Snapshot-Rotate-Error -end - -kvs -> hasher: Create JSON data string hash - -alt hash-created - hasher --> kvs: Data hash -else hash-create-error - hasher --> kvs: Hash-Calc-Error - kvs --> actor: Hash-Calc-Error -end - -kvs -> fs: Write JSON data string to file - -alt file-write - fs --> kvs: File successfully written -else file-write-error - fs --> kvs: File-Write-Error - kvs --> actor: File-Write-Error -end - -kvs -> fs: Write JSON data hash to file - -alt file-hash-write - fs --> kvs: Hash file successfully written - kvs --> actor: Flush successful -else file-hash-write-error - fs --> kvs: File-Hash-Write-Error - kvs --> actor: File-Hash-Write-Error -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml deleted file mode 100644 index 064e248911..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml +++ /dev/null @@ -1,20 +0,0 @@ -@startuml - -title Sequence Diagram: Read Key from KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Get value for key - -alt key-exists - kvs --> actor: Return value for key -else key-doesnt-exist - alt default-exists - kvs --> actor: Return default value for key - else default-doesnt-exist - kvs --> actor: Key-Not-Found error - end -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml deleted file mode 100644 index c4cdbaffaa..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml +++ /dev/null @@ -1,49 +0,0 @@ -@startuml - -title Sequence Diagram: Read Data into Local Representation (KvsValue) - -participant "Builder" as actor -participant "«component» :kvs" as kvs -participant "«component» :TinyJSON" as json_parser -participant "«component» :fs" as fs -participant "«component» :Adler32" as hasher - -actor -> kvs: Open KVS - -kvs -> fs: Read defaults file - -alt file-exists - fs --> kvs: Defaults file content (JSON) -else file-based-error - fs --> kvs: File-Error - kvs -> actor: File-Error -end - -kvs -> fs: Read defaults file hash - -alt file-exists - fs --> kvs: Defaults file hash -else file-based-error - fs --> kvs: File-Error - kvs -> actor: File-Error -end - -kvs -> hasher: Generate defaults file hash -hasher --> kvs: Defaults file generated hash - -alt hash-matches - kvs -> json_parser: Parse JSON data -else hash-match-error - kvs -> actor: Hash-Error -end - -alt parsing-success - json_parser --> kvs: Parsed JSON object -else parsing-based-error - json_parser -> kvs: Parser-Error - kvs -> actor: Parser-Error -end - -kvs --> actor: KVS instance - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml deleted file mode 100644 index a18eab3b8a..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml +++ /dev/null @@ -1,19 +0,0 @@ -@startuml - -title Sequence Diagram: Restore Snapshot - -participant "User" as actor -participant "«component» :kvs" as kvs -participant "«component» :snapshot" as snapshot - -actor -> kvs: Restore snapshot - -alt snapshot-found - snapshot --> kvs: Snapshot restored into local representation - kvs --> actor: Snapshot restored successfully -else snapshot-error - snapshot --> kvs: Snapshot-Not-Available-Error - kvs --> actor: Snapshot-Not-Available-Error -end - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml deleted file mode 100644 index b34c24cc20..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml +++ /dev/null @@ -1,11 +0,0 @@ -@startuml - -title Sequence Diagram: Write Key to KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Set value for key -kvs --> actor: Value set for key - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml deleted file mode 100644 index e8e2e1750d..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml +++ /dev/null @@ -1,23 +0,0 @@ -@startuml - -interface Kvs { - open - flush_on_exit - reset - get_all_keys - key_exists - get_value - get_default_value - has_default_value - set_default_value - set_value - remove_key - flush - snapshot_count - snapshot_max_count - snapshot_restore - get_kvs_filename - get_hash_filename -} - -@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml deleted file mode 100644 index e016ae104a..0000000000 --- a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml +++ /dev/null @@ -1,32 +0,0 @@ -@startuml -allowmixing - -title Static View - kvs - -!include kvs_interface.puml - - -skinparam package { - BackgroundColor #E0E0D0 - BorderColor Black - backgroundColor<<feature>> yellow -} - -skinparam component { - backgroundColor<<component>> white -} - -' Define Features -package "kvs" <<feature>> { - component kvs <<component>> - component fs <<component>> - component tiny_json <<component>> -} - -kvs -u- Kvs - -kvs ..> tiny_json : use -kvs ..> fs : use - - -@enduml diff --git a/docs/features/persistency/kvs/architecture/feature_architecture.rst b/docs/features/persistency/kvs/architecture/feature_architecture.rst deleted file mode 100644 index a4b54f5b8e..0000000000 --- a/docs/features/persistency/kvs/architecture/feature_architecture.rst +++ /dev/null @@ -1,139 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Feature Architecture : persistency/kvs -====================================== - -Overview --------- - -- kvs provides the capability to efficiently store, retrieve, and - manage key-value pairs in a persistent storage system. - -Description ------------ - -- kvs organize data as pairs, where each unique key is associated with a specific value. - The key acts as a unique identifier for getting the value. -- The data is persisted in JSON format to the file system, providing a human-readable, - and widely supported way to store and manage key-value pairs. -- The JSON data persisted is according to RFC-8259. - -Rationale Behind Architecture Decomposition -******************************************* - -- The architecture is decomposed to include a dedicated JSON parser component (TinyJSON) to facilitate the persistent storage of data in JSON format. -- The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. - - -Static Architecture -------------------- - -.. feat_arc_sta:: Static Architecture - :id: feat_arc_sta__kvs__static - :security: YES - :safety: ASIL_B - :includes: logic_arc_int__kvs__interface - :fulfils: feat_req__kvs__default_value_retrieval,feat_req__kvs__default_values,feat_req__kvs__events,feat_req__kvs__integrity_check,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__stable_api,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values - :status: valid - - .. uml:: _assets/kvs_static_view.puml - -Dynamic Architecture --------------------- - -.. feat_arc_dyn:: KVS Builder - :id: feat_arc_dyn__kvs__builder_pattern - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b - :status: valid - - .. uml:: _assets/kvs_dyn_builder.puml - -.. feat_arc_dyn:: Check if key contains default value - :id: feat_arc_dyn__kvs__check_key_default - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval - :status: valid - - .. uml:: _assets/kvs_dyn_check_value_default.puml - -.. feat_arc_dyn:: Delete key from KVS instance - :id: feat_arc_dyn__kvs__delete_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b - :status: valid - - .. uml:: _assets/kvs_dyn_delete_data_key.puml - -.. feat_arc_dyn:: Flush to permanent storage - :id: feat_arc_dyn__kvs__flush - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__snapshots,feat_req__kvs__integrity_check,feat_req__kvs__snapshots - :status: valid - - .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml - -.. feat_arc_dyn:: Read key value - :id: feat_arc_dyn__kvs__read_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval - :status: valid - - .. uml:: _assets/kvs_dyn_read_data_key.puml - -.. feat_arc_dyn:: Read data from permanent storage - :id: feat_arc_dyn__kvs__read_data_from_storage - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__persist_data,feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__snapshots - :status: valid - - .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml - -.. feat_arc_dyn:: Write value to key - :id: feat_arc_dyn__kvs__write_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__supported_datatypes_keys,feat_req__kvs__supported_datatypes_values - :status: valid - - .. uml:: _assets/kvs_dyn_write_data_key.puml - -.. feat_arc_dyn:: Restore snapshop - :id: feat_arc_dyn__kvs__snapshot_restore - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__snapshots,feat_req__kvs__persist_data,feat_req__kvs__persistency - :status: valid - - .. uml:: _assets/kvs_dyn_restore_snapshot.puml - - -Logical Interfaces ------------------- - -.. feat_arc_int:: Ikvs - :id: feat_arc_int__kvs__interface - :security: YES - :safety: ASIL_B - :fulfils: feat_req__kvs__safety_asil_b,feat_req__kvs__stable_api - :status: valid - - .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst deleted file mode 100644 index 335d087369..0000000000 --- a/docs/features/persistency/kvs/architecture/index.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Architecture -############# - -.. note:: - For now we store the component architecture in the feature tree, because multi-repo docs are not yet supported. - Once this support becomes available the component architecture will be moved to the module. - -.. toctree:: - :titlesonly: - - feature_architecture diff --git a/docs/features/persistency/requirements/component_requirements.rst b/docs/features/persistency/requirements/component_requirements.rst deleted file mode 100644 index 12180dc6a8..0000000000 --- a/docs/features/persistency/requirements/component_requirements.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Component Requirements -###################### - -.. comp_req:: Key Handling - :id: comp_req__kvs__key_handling - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__supported_datatypes_keys - :status: valid - - The component shall accept keys that consist solely of alphanumeric characters, underscores, or dashes. - The component shall encode each key as valid UTF-8. - The component shall guarantee that each key is unique. - The component shall limit the maximum length of a key to 32 bytes. - -.. comp_req:: Value Handling - :id: comp_req__kvs__value_handling - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__supported_datatypes_values,feat_req__kvs__default_values - :status: valid - - The component shall accept only values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. - The component shall serialize and deserialize all values to and from JSON. - The component shall limit the maximum length of a value to 1024 bytes. - The component shall support unset values and shall provide a default value when a value is unset. - The component shall allow resetting a value to its default if a default is defined. - -.. comp_req:: Default Value Handling - :id: comp_req__kvs__default_value_handling - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__default_values,feat_req__kvs__default_value_retrieval,feat_req__kvs__default_value_reset,feat_req__kvs__default_value_file - :status: valid - - The component shall accept default values of only permitted value data types. - The component shall provide an API to retrieve default values. - The component shall allow configuration of default values in code or in a separate configuration file. - The component shall secure the configuration file for default values with an associated checksum file when default values are stored in a file. - -.. comp_req:: Constraint Configuration - :id: comp_req__kvs__constraints - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__config_file - :status: valid - - The component shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. - -.. comp_req:: Language Agnostic - :id: comp_req__kvs__language_agnostic - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__cpp_rust_interoperability - :status: valid - - The component shall provide an API that supports bindings to other languages or shall use a storage and memory exchange format that is adaptable to other languages. - -.. comp_req:: Concurrency - :id: comp_req__kvs__concurrency - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__intra_process_comm - :status: valid - - The component shall implement thread-safe mechanisms to enable concurrent access to data without data races. - -.. comp_req:: Multi-Instance - :id: comp_req__kvs__multi_instance - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__multiple_kvs - :status: valid - - The component shall manage all runtime variables within an instance to enable creation and use of multiple KVS instances concurrently within a single software architecture element. - -.. comp_req:: Persistent Data Storage - :id: comp_req__kvs__persistent_data_storage - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__persistency,feat_req__kvs__integrity_check,feat_req__kvs__persist_data - :status: valid - - The component shall use the file API and the JSON data format to persist data. - The component shall generate a checksum for each data file and shall store it alongside the data. - The component shall verify the checksum when loading data. - -.. comp_req:: Persistent Data Schema Handling - :id: comp_req__kvs__persistent_data_schema - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__versioning,feat_req__kvs__update_mechanism - :status: valid - - The component shall not provide built-in versioning. - The component shall use a JSON file storage format that enables the application to implement versioning, including upgrade and downgrade paths, as needed. - -.. comp_req:: Snapshots - :id: comp_req__kvs__snapshots - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__snapshots - :status: valid - - The component shall create a snapshot each time data is stored. - The component shall maintain a configurable maximum number of snapshots. - The component shall assign the ID 1 to the newest snapshot and shall increment the IDs of older snapshots accordingly. - The component shall rotate and delete the oldest snapshot when the maximum number is reached. - The component shall allow restoration of a snapshot by its ID. - The component shall allow deletion of individual snapshots. - -.. comp_req:: Develop Mode - :id: comp_req__kvs__dev_mode - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__dev_mode - :status: valid - - The component shall provide a developer mode that can be enabled during build time to display debugging and internal information. - -.. comp_req:: Async API - :id: comp_req__kvs__async_api - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__async_api - :status: valid - - The component shall provide an asynchronous API in addition to the standard API. - -.. comp_req:: Permission Handling - :id: comp_req__kvs__permission_handling - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__kvs__access_control - :status: valid - - The component shall rely on the underlying filesystem for access and permission management and shall not implement its own access or permission controls. - The component shall report any access or permission errors encountered at the filesystem level to the application. - -.. comp_req:: Callback Support - :id: comp_req__kvs__callback_support - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__kvs__events - :status: valid - - The component shall provide an API for registering callbacks that are triggered by data change events. diff --git a/docs/features/persistency/requirements/feature_requirements.rst b/docs/features/persistency/requirements/feature_requirements.rst deleted file mode 100644 index 656c3e53a4..0000000000 --- a/docs/features/persistency/requirements/feature_requirements.rst +++ /dev/null @@ -1,272 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Feature Requirements -#################### - -.. feat_req:: C++ & Rust Interoperability - :id: feat_req__kvs__cpp_rust_interoperability - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__dev_experience__prog_languages - :status: valid - - The KVS system shall provide access through both C++ and Rust interfaces. - -.. feat_req:: Maximum Size - :id: feat_req__kvs__maximum_size - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: invalid - - The KVS system shall support specification of its maximum capacity at compile time. - -.. feat_req:: Multiple KVS per Software Architecture Element - :id: feat_req__kvs__multiple_kvs - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall allow instantiating multiple independent stores per software architecture element. - -.. feat_req:: Supported Datatypes (Keys) - :id: feat_req__kvs__supported_datatypes_keys - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support UTF-8 encoded strings as valid key types. - -.. feat_req:: Supported Datatypes (Values) - :id: feat_req__kvs__supported_datatypes_values - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support storing both primitive and non-primitive datatypes as values. - The supported datatypes shall match those used by the IPC feature. - -.. feat_req:: Default Values - :id: feat_req__kvs__default_values - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support predefined default values for keys. - -.. feat_req:: Default Value Retrieval - :id: feat_req__kvs__default_value_retrieval - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support retrieving the default value associated with a key. - -.. feat_req:: Default Value Reset - :id: feat_req__kvs__default_value_reset - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support resetting a single key or all keys to their respective default values. - -.. feat_req:: Persistency - :id: feat_req__kvs__persistency - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall persist stored data and provide an API to explicitly trigger persistence. - -.. feat_req:: Integrity Check - :id: feat_req__kvs__integrity_check - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall detect and report data corruption. - Note: Implementation depends on AoUs. - -.. feat_req:: Versioning - :id: feat_req__kvs__versioning - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support versioning for different layout configurations. - -.. feat_req:: Update Mechanism - :id: feat_req__kvs__update_mechanism - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall implement mechanisms to upgrade from one version to another, including multi-version jumps. - -.. feat_req:: Snapshots - :id: feat_req__kvs__snapshots - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall support explicit creation of snapshots identified by unique IDs and allow rollback to previous snapshots. - Snapshots shall also be deletable. - -.. feat_req:: Tooling - :id: feat_req__kvs__tooling - :reqtype: Non-Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__functiona_req__support_of_store - :status: valid - - The KVS system shall provide tooling support for viewing and modifying key-value pairs during development and debugging. - -.. feat_req:: Stable APIs - :id: feat_req__kvs__stable_api - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__communication__stable_app_inter - :status: valid - - The KVS API shall remain stable throughout its lifecycle while enabling the addition of new functionalities. - -.. feat_req:: Variant management support - :id: feat_req__kvs__variant_management - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__overall_goals__variant_management - :status: valid - - The KVS shall ensure compatibility across different architectures and versions. - -.. feat_req:: Set default key values via file - :id: feat_req__kvs__default_value_file - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__functional_req__file_based - :status: valid - - The KVS shall support the configuration of default key values using an external file. - -.. feat_req:: Configure limits via file - :id: feat_req__kvs__config_file - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__functional_req__file_based - :status: valid - - The KVS shall support the configuration of memory and other resource limits via a configuration file. - -.. feat_req:: Store persistent data - :id: feat_req__kvs__persist_data - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__functional_req__data_persistency - :status: valid - - The KVS shall support storing and loading its data to and from persistent storage. - -.. feat_req:: Support engineering and field mode - :id: feat_req__kvs__dev_mode - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__dependability__safety_features - :status: valid - - The KVS shall provide both engineering (developer) and field modes. - The engineering mode shall allow unrestricted data access. - -.. feat_req:: Provide an async API - :id: feat_req__kvs__async_api - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__dependability__availability, stkh_req__app_architectures__support_request - :status: valid - - The KVS shall provide an asynchronous API for accessing and manipulating data. - -.. feat_req:: Separate data stores - :id: feat_req__kvs__access_control - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__dependability__security_features - :status: valid - - The KVS shall ensure that only authorized components can access individual data stores. - -.. feat_req:: Data-change events - :id: feat_req__kvs__events - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_data - :status: valid - - The KVS shall provide an API that allows for the registration of callback - functions. These callbacks shall be invoked in response to specific events, - such as when keys are changed or removed. - -.. feat_req:: Fast access - :id: feat_req__kvs__fast_access - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__execution_model__short_app_cycles - :status: valid - - The KVS shall ensure that key operations are typically completed within 5 milliseconds. - -.. feat_req:: Intra-Process Data Access - :id: feat_req__kvs__intra_process_comm - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: stkh_req__communication__intra_process - :status: valid - - The KVS shall support concurrent intra-process data access. diff --git a/docs/features/persistency/requirements/index.rst b/docs/features/persistency/requirements/index.rst index 323ef780cc..a9cf044a00 100644 --- a/docs/features/persistency/requirements/index.rst +++ b/docs/features/persistency/requirements/index.rst @@ -15,7 +15,6 @@ Requirements ############ -<<<<<<< HEAD:docs/features/persistency/requirements/index.rst .. feat_req:: C++ & Rust Interoperability :id: feat_req__persistency__cpp_rust_interop :reqtype: Non-Functional @@ -271,10 +270,3 @@ Requirements :status: valid The KVS shall support concurrent intra-process data access. -======= -.. toctree:: - :titlesonly: - - feature_requirements - component_requirements ->>>>>>> 13a7ca4ac (persistency_kvs: component requirements):docs/features/persistency/kvs/requirements/index.rst diff --git a/docs/features/persistency/safety_analysis/dfa.rst b/docs/features/persistency/safety_analysis/dfa.rst new file mode 100644 index 0000000000..8aed7eed32 --- /dev/null +++ b/docs/features/persistency/safety_analysis/dfa.rst @@ -0,0 +1,868 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Persistency DFA +############### + +.. document:: DFA + :id: doc__persistency_dfa + :status: draft + :safety: ASIL_B + :tags: feature_persistency + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_01 + | :violation_cause: Reused software module. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_02 + | :violation_cause: Libraries. . N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_04 + | :violation_cause: Basic software. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_05 + | :violation_cause: Operating system including scheduler. Platformebene. Nicht von Middleware handlebar + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_06 + | :violation_cause: Any service stack, e.g. communication stack. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_07 + | :violation_cause: Configuration data. Return values might be falsified. + | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__persistency__integrity_check + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_09 + | :violation_cause: Execution time. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SR_01_10 + | :violation_cause: Allocated memory. Diskussion aktuell in Feature-Community. JSON kann das, sollte aber eigentlich nicht erlaubt sein + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_01 + | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) <- Checken ob das Fehlerbild überhaupt passt. 1. Satzteil nicht passen zu 2.> + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_02 + | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information. Fehlerhafte ausführung oder nichtverfügbarkeit vom feature + | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_03 + | :violation_cause: Insertion / sequence of information wie CO_01_02 + | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_04 + | :violation_cause: Corruption of information, inconsistent data wie CO_01_02 + | :mitigation: < NONE|ID from Feature Requirement> keine Erkennung + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_05 + | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_06 + | :violation_cause: Information from a sender received by only a subset of the receivers. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: CO_01_07 + | :violation_cause: Blocking access to a communication channel N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_02 + | :violation_cause: Configuration data. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_03 + | :violation_cause: Constants, or variables, being global to the two software functions. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_04 + | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SI_01_05 + | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function. Unklar was das Fehlerbild ist + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_01 + | :violation_cause: Memory miss-allocation and leaks. Platformebene + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_02 + | :violation_cause: Read/Write access to memory allocated to another software element. Platformebene + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_03 + | :violation_cause: Stack/Buffer under-/overflow. Könnte passieren, ist aber unwahrscheinlich in RUST. Recursive Funktionen könnten die Ursache sein. + | :mitigation: < NONE|ID from Feature Requirement> Compilerüberwachung / AoU + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_04 + | :violation_cause: Deadlocks. Könnten auftreten. Würde von Applikation verursacht werden. KVS kann da nichts machen + | :mitigation: < NONE|ID from Feature Requirement> AoU + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_05 + | :violation_cause: Livelocks wie UI_01_04 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_06 + | :violation_cause: Blocking of execution. Feature is not available. + | :mitigation: < NONE|ID from Feature Requirement> AoU + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_07 + | :violation_cause: Incorrect allocation of execution time. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_08 + | :violation_cause: Incorrect execution flow N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_09 + | :violation_cause: Incorrect synchronization between software elements N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_10 + | :violation_cause: CPU time depletion N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_11 + | :violation_cause: Memory depletion N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: UI_01_12 + | :violation_cause: Other HW unavailability N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_02 + | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_03 + | :violation_cause: Same personal + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_04 + | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: Persistency + | :verifies: feat_arc_dyn__persistency__check_key_default + | :id: feat_saf_DFA__persistency__check_key_default + | :violation_id: SC_01_05 + | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + + + + + + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_01 + | :violation_cause: Reused software modules + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_02 + | :violation_cause: Libraries + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_04 + | :violation_cause: Basic software + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_05 + | :violation_cause: Operating system including scheduler + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_06 + | :violation_cause: Any service stack, e.g. communication stack + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_07 + | :violation_cause: Configuration data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_09 + | :violation_cause: Execution time + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SR_01_10 + | :violation_cause: Allocated memory + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_01 + | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_02 + | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_03 + | :violation_cause: Insertion / sequence of information + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_04 + | :violation_cause: Corruption of information, inconsistent data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_05 + | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_06 + | :violation_cause: Information from a sender received by only a subset of the receivers + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: CO_01_07 + | :violation_cause: Blocking access to a communication channel + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SI_01_02 + | :violation_cause: Configuration data + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SI_01_03 + | :violation_cause: Constants, or variables, being global to the two software functions + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SI_01_04 + | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SI_01_05 + | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_01 + | :violation_cause: Memory miss-allocation and leaks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_02 + | :violation_cause: Read/Write access to memory allocated to another software element + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_03 + | :violation_cause: Stack/Buffer under-/overflow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_04 + | :violation_cause: Deadlocks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_05 + | :violation_cause: Livelocks + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_06 + | :violation_cause: Blocking of execution + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_07 + | :violation_cause: Incorrect allocation of execution time + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_08 + | :violation_cause: Incorrect execution flow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_09 + | :violation_cause: Incorrect synchronization between software elements + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_10 + | :violation_cause: CPU time depletion + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_11 + | :violation_cause: Memory depletion + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: UI_01_12 + | :violation_cause: Other HW unavailability + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SC_01_02 + | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SC_01_03 + | :violation_cause: Same personal + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SC_01_04 + | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_dfa:: <Element descriptor> + | :verifies: <Feature architecture> + | :id: feat_saf_DFA__<Feature>__<Element descriptor> + | :violation_id: SC_01_05 + | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> diff --git a/docs/features/persistency/safety_analysis/fmea.rst b/docs/features/persistency/safety_analysis/fmea.rst new file mode 100644 index 0000000000..7097c89ac2 --- /dev/null +++ b/docs/features/persistency/safety_analysis/fmea.rst @@ -0,0 +1,393 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Persistency Safety Analysis +########################### + +.. document:: Safety Analysis + :id: doc__persistency_safety_analysis + :status: draft + :safety: ASIL_B + :tags: feature_persistency + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_01 + | :failure_effect: Message is not received. User is not able to use the feature. Middleware cant be used.A + | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_02 + | :failure_effect: message received too late. User might not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_03 + | :failure_effect: message received too early. No impact / feature reacts only if triggered on the trigger. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_04 + | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost). N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_05 + | :failure_effect: message is corrupted. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_06 + | :failure_effect: message is not sent. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: MF_01_07 + | :failure_effect: message is unintended sent. Covered by MF_01_01 + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: CO_01_01 + | :failure_effect: minimum constraint boundary is violated. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: CO_01_02 + | :failure_effect: maximum constraint boundary is violated. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_01 + | :failure_effect: Process calculates wrong result(s). Feature is not usable. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_02 + | :failure_effect: processing too slow. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_03 + | :failure_effect: processing too fast. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_04 + | :failure_effect: loss of execution. User is not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_05 + | :failure_effect: processing changes to arbitrary process. N/A + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: feat_arc_sta__persistency__static + | :id: feat_saf_FMEA__persistency__open_KVS + | :failure_mode: EX_01_06 + | :failure_effect: processing is not complete (infinite loop). User is not able to use the feature. Middleware cant be used. + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + + + + + + + + + + + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_01 + | :failure_effect: message is not received + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_02 + | :failure_effect: message received too late + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_03 + | :failure_effect: message received too early + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_04 + | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_05 + | :failure_effect: message is corrupted + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_06 + | :failure_effect: message is not sent + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: MF_01_07 + | :failure_effect: message is unintended sent + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: CO_01_01 + | :failure_effect: minimum constraint boundary is violated + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: CO_01_02 + | :failure_effect: maximum constraint boundary is violated + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_01 + | :failure_effect: Process calculates wrong result(s) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_02 + | :failure_effect: processing too slow + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_03 + | :failure_effect: processing too fast + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_04 + | :failure_effect: loss of execution + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_05 + | :failure_effect: processing changes to arbitrary process + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> + + | .. feat_saf_fmea:: Persistency + | :verifies: <Feature architecture> + | :id: feat_saf_FMEA__persistency__<Element descriptor> + | :failure_mode: EX_01_06 + | :failure_effect: processing is not complete (infinite loop) + | :mitigation: < NONE|ID from Feature Requirement> + | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> + | :mitigation_coverage: <0..100%> + | :sufficient: <yes|no> + | :argument: <text to argument why mitigation is sufficient> + | :status: <valid|invalid> diff --git a/docs/features/persistency/safety_planning/index.rst b/docs/features/persistency/safety_planning/index.rst new file mode 100644 index 0000000000..c45fd37406 --- /dev/null +++ b/docs/features/persistency/safety_planning/index.rst @@ -0,0 +1,130 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _feature_safety_wp_template: + +Feature Safety Planning +======================= + +.. list-table:: Feature <feature> Workproducts + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - :need:`wp__feat_request` + - :need:`gd_temp__change__feature_request` + - :ndf:`copy('status', need_id='gd_temp__change__feature_request')` + - https://github.com/eclipse-score/score/issues/760 + - :need:`doc__feature_name` + - :ndf:`copy('status', need_id='doc__feature_name')` + + * - :need:`wp__requirements__feat` + - :need:`gd_temp__req__feat_req` + - :ndf:`copy('status', need_id='gd_temp__req__feat_req')` + - https://github.com/eclipse-score/score/issues/960 + - :doc:`../requirements/index` + - see below + + * - :need:`wp__requirements__feat_aou` + - :need:`gd_temp__req__aou_req` + - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` + - https://github.com/eclipse-score/score/issues/960 + - :doc:`../requirements/index` + - see below + + * - :need:`wp__feature_arch` + - :need:`gd_temp__arch__feature` + - :ndf:`copy('status', need_id='gd_temp__arch__feature')` + - https://github.com/eclipse-score/score/issues/1020 + - :doc:`../architecture/index` + - see below + + * - :need:`wp__feature_safety_analysis` + - <link to process> + - <automated> + - https://github.com/eclipse-score/score/issues/965 + - :doc:`../safety_analysis/doc__persistency_safety_analysis` + - <automated> + + * - :need:`wp__feature_dfa` + - <Link to process> + - <Process status> + - https://github.com/eclipse-score/score/issues/965 + - :doc:`../safety_analysis/doc__persistency_dfa` + - <automated> + + * - :need:`wp__requirements__inspect` + - :need:`gd_chklst__req__inspection` + - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__sw_arch_verification` + - :need:`gd_chklst__arch__inspection_checklist` + - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` + - n/a + - Checklist used in Pull Request Review + - n/a + + * - :need:`wp__verification__feat_int_test` + - :need:`gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + - <link to issue> + - https://github.com/eclipse-score/score/issues/964 + - <automated> + +.. attention:: + The above table must be updated according to your feature safety planning. + + - Create and link the issues to plan the work products (according to :need:`gd_guidl__saf_plan_definitions`) + - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`gd_guidl__saf_package`) + +Feature Requirements Status +--------------------------- + +.. needtable:: + :style: table + :types: feat_req + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title + +Feature AoU Status +------------------ + +.. needtable:: + :style: table + :types: aou_req + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title + +Feature Architecture Status +--------------------------- + +.. needtable:: + :style: table + :types: feat_arc_sta; feat_arc_dyn + :tags: feature_name + :columns: id;status + :colwidths: 25,25 + :sort: title diff --git a/docs/modules/persistency/kvs/docs/requirements/index.rst b/docs/modules/persistency/kvs/docs/requirements/index.rst index 9e0d6d7b6f..58ee48a028 100644 --- a/docs/modules/persistency/kvs/docs/requirements/index.rst +++ b/docs/modules/persistency/kvs/docs/requirements/index.rst @@ -12,61 +12,164 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Requirements -############ +Component Requirements +###################### -.. document:: [Your Component Name] Requirements - :id: doc__component_name_requirements - :status: draft - :safety: ASIL_D - :realizes: wp__requirements__comp - :tags: template +.. comp_req:: Key Handling + :id: comp_req__persistency__key_handling + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__support_datatype_keys + :status: valid -.. attention:: - The above directive must be updated according to your Component. + The component shall accept keys that consist solely of alphanumeric characters, underscores, or dashes. + The component shall encode each key as valid UTF-8. + The component shall guarantee that each key is unique. + The component shall limit the maximum length of a key to 32 bytes. - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs +.. comp_req:: Value Handling + :id: comp_req__persistency__value_handling + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__support_datatype_value,feat_req__persistency__default_values + :status: valid -<Headlines (for the list of requirements if structuring is needed)> -=================================================================== + The component shall accept only values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. + The component shall serialize and deserialize all values to and from JSON. + The component shall limit the maximum length of a value to 1024 bytes. + The component shall support unset values and shall provide a default value when a value is unset. + The component shall allow resetting a value to its default if a default is defined. -.. comp_req:: Some Title - :id: comp_req__component_name__some_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :satisfies: feat_req__feature_name__some_title - :status: invalid +.. comp_req:: Default Value Handling + :id: comp_req__persistency__default_value_handling + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__default_values,feat_req__persistency__default_value_retrieval,feat_req__persistency__default_value_reset,feat_req__persistency__default_value_file + :status: valid - The Component shall do xyz to another component to bring it to this condition at this time + The component shall accept default values of only permitted value data types. + The component shall provide an API to retrieve default values. + The component shall allow configuration of default values in code or in a separate configuration file. + The component shall secure the configuration file for default values with an associated checksum file when default values are stored in a file. - Note: (optional, not to be verified) +.. comp_req:: Constraint Configuration + :id: comp_req__persistency__constraints + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__config_file + :status: valid -.. attention:: - The above directive must be updated according to your component requirements. + The component shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. - - Replace the example content by the real content for your first requirement - - Set the status to valid and start the review/merge process - - Add other needed requirements for your component +.. comp_req:: Language Agnostic + :id: comp_req__persistency__language_agnostic + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__cpp_rust_interoperability + :status: valid -.. aou_req:: Next Title - :id: aou_req__component_name__next_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :status: invalid + The component shall provide an API that supports bindings to other languages or shall use a storage and memory exchange format that is adaptable to other languages. - The Component User shall do xyz to use the component safely +.. comp_req:: Concurrency + :id: comp_req__persistency__concurrency + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__intra_process_comm + :status: valid -.. attention:: - The above directives must be updated according to your feature requirements. + The component shall implement thread-safe mechanisms to enable concurrent access to data without data races. - - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) - - Set the status to valid and start the review/merge process - - Add other needed requirements for your feature +.. comp_req:: Multi-Instance + :id: comp_req__persistency__multi_instance + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__multiple_kvs + :status: valid -.. needextend:: "component_name" in id - :+tags: component_name + The component shall manage all runtime variables within an instance to enable creation and use of multiple KVS instances concurrently within a single software architecture element. + +.. comp_req:: Persistent Data Storage + :id: comp_req__persistency__persist_data_storage + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__persist_data + :status: valid + + The component shall use the file API and the JSON data format to persist data. + The component shall generate a checksum for each data file and shall store it alongside the data. + The component shall verify the checksum when loading data. + +.. comp_req:: Persistent Data Schema Handling + :id: comp_req__persistency__persistent_data_schema + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__versioning,feat_req__persistency__update_mechanism + :status: valid + + The component shall not provide built-in versioning. + The component shall use a JSON file storage format that enables the application to implement versioning, including upgrade and downgrade paths, as needed. + +.. comp_req:: Snapshots + :id: comp_req__persistency__snapshots + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__snapshots + :status: valid + + The component shall create a snapshot each time data is stored. + The component shall maintain a configurable maximum number of snapshots. + The component shall assign the ID 1 to the newest snapshot and shall increment the IDs of older snapshots accordingly. + The component shall rotate and delete the oldest snapshot when the maximum number is reached. + The component shall allow restoration of a snapshot by its ID. + The component shall allow deletion of individual snapshots. + +.. comp_req:: Develop Mode + :id: comp_req__persistency__dev_mode + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__dev_mode + :status: valid + + The component shall provide a developer mode that can be enabled during build time to display debugging and internal information. + +.. comp_req:: Async API + :id: comp_req__persistency__async_api + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__async_api + :status: valid + + The component shall provide an asynchronous API in addition to the standard API. + +.. comp_req:: Permission Handling + :id: comp_req__persistency__permission_handling + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: feat_req__persistency__access_control + :status: valid + + The component shall rely on the underlying filesystem for access and permission management and shall not implement its own access or permission controls. + The component shall report any access or permission errors encountered at the filesystem level to the application. + +.. comp_req:: Callback Support + :id: comp_req__persistency__callback_support + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: feat_req__persistency__events + :status: valid + + The component shall provide an API for registering callbacks that are triggered by data change events. From 2e78fbec5d4a5bcabf3118159300848b59ec14e1 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 4 Jun 2025 08:05:43 +0200 Subject: [PATCH 032/102] persistency_kvs: integrated feature template Note: This doesn't build completely and contains some id errors. Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../feature_name/architecture/index.rst | 155 ---- docs/features/feature_name/index.rst | 192 ---- .../feature_name/requirements/index.rst | 77 -- .../feature_name/safety_analysis/dfa.rst | 868 ------------------ .../feature_name/safety_analysis/fmea.rst | 393 -------- .../feature_name/safety_planning/index.rst | 130 --- .../persistency/architecture/index.rst | 6 +- docs/features/persistency/index.rst | 3 + .../persistency/docs/safety_mgt/index.rst | 4 - .../safety_mgt/module_safety_package_fdr.rst | 73 -- .../docs/safety_mgt/module_safety_plan.rst | 357 ------- .../safety_mgt/module_safety_plan_fdr.rst | 348 ------- .../json/docs/architecture/index.rst | 130 --- docs/modules/persistency/json/docs/index.rst | 12 +- .../json/docs/requirements/index.rst | 72 -- .../json/docs/safety_analysis/dfa.rst | 53 -- .../json/docs/safety_analysis/fmea.rst | 53 -- .../kvs/docs/architecture/index.rst | 20 +- docs/modules/persistency/kvs/docs/index.rst | 8 +- .../kvs/docs/safety_analysis/dfa.rst | 8 +- .../kvs/docs/safety_analysis/fmea.rst | 8 +- 21 files changed, 32 insertions(+), 2938 deletions(-) delete mode 100644 docs/features/feature_name/architecture/index.rst delete mode 100644 docs/features/feature_name/index.rst delete mode 100644 docs/features/feature_name/requirements/index.rst delete mode 100644 docs/features/feature_name/safety_analysis/dfa.rst delete mode 100644 docs/features/feature_name/safety_analysis/fmea.rst delete mode 100644 docs/features/feature_name/safety_planning/index.rst delete mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst delete mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst delete mode 100644 docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst delete mode 100644 docs/modules/persistency/json/docs/architecture/index.rst delete mode 100644 docs/modules/persistency/json/docs/requirements/index.rst delete mode 100644 docs/modules/persistency/json/docs/safety_analysis/dfa.rst delete mode 100644 docs/modules/persistency/json/docs/safety_analysis/fmea.rst diff --git a/docs/features/feature_name/architecture/index.rst b/docs/features/feature_name/architecture/index.rst deleted file mode 100644 index ea48cde157..0000000000 --- a/docs/features/feature_name/architecture/index.rst +++ /dev/null @@ -1,155 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _feature_architecture_template: - -Feature Architecture -==================== - -.. document:: [Your Feature Name] Architecture - :id: doc__feature_name_architecture - :status: draft - :safety: ASIL_D - :realizes: wp__feature_arch - :tags: template - -.. attention:: - The above directive must be updated according to your Feature. - - - Modify ``Your Feature Name`` to be your Feature Name - - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Overview --------- -Brief summary - -Description ------------ - -General Description - -Design Decisions - -Design Constraints - -Requirements ------------- - -.. code-block:: none - - .. needtable:: Overview of Feature Requirements - :style: table - :columns: title;id - :filter: search("feat_arch_sta__archdes$", "fulfils_back") - :colwidths: 70,30 - - -Rationale Behind Architecture Decomposition -******************************************* -mandatory: a motivation for the decomposition - -.. note:: Common decisions across features / cross cutting concepts is at the high level. - -Static Architecture -------------------- - -.. feat_arc_sta:: Static View - :id: feat_arc_sta__feature_name__static_view - :security: YES - :safety: ASIL_D - :status: invalid - :fulfils: feat_req__feature_name__some_title - :includes: logic_arc_int__feature_name__interface_name - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_feature(need(), needs) }} - -Dynamic Architecture --------------------- - -.. feat_arc_dyn:: Dynamic View - :id: feat_arc_dyn__feature_name__dynamic_view - :security: YES - :safety: ASIL_D - :status: invalid - :fulfils: feat_req__feature_name__some_title - - put here a sequence diagram - -Logical Interfaces ------------------- - -.. logic_arc_int:: Interface Name - :id: logic_arc_int__feature_name__interface_name - :security: YES - :safety: ASIL_D - :status: invalid - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_interface(need(), needs) }} - -.. logic_arc_int_op:: Operation - :id: logic_arc_int_op__feature_name__operation - :security: YES - :safety: ASIL_D - :status: invalid - :included_by: logic_arc_int__feature_name__interface_name - -Module Viewpoint ----------------- - -The following modules are needed to be defined to be able to draw the static feature view. -They will be replaced by linking the proper module definitions in the used module's repositories as soon as those exist. - -.. mod_view_sta:: Module Name - :id: mod_view_sta__feature_name__module_name - :includes: comp_arc_sta__feature_name__component_name - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_module(need(), needs) }} - -Used Components ---------------- - -The following components are needed to be defined to be able to draw the static feature view. -They will be replaced by linking the proper SW component definitions in the used module's repositories as soon as those exist. - -.. comp_arc_sta:: Component Name - :id: comp_arc_sta__feature_name__component_name - :safety: ASIL_D - :security: YES - :status: invalid - :implements: logic_arc_int__feature_name__interface_name - -.. note:: - Architecture can be split into multiple files, it is an High level architecture_design - which can be shown without actual c++/rust interfaces and data types - and there will be link to lower level architecture till code to get actual api descriptions. - -.. attention:: - The above directives must be updated according to your feature architecture. - - - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) - - Set the status to valid and start the review/merge process diff --git a/docs/features/feature_name/index.rst b/docs/features/feature_name/index.rst deleted file mode 100644 index 61b16cda74..0000000000 --- a/docs/features/feature_name/index.rst +++ /dev/null @@ -1,192 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _feature_template: - -[Your Feature Name] -################### - -.. note:: Document header - -.. document:: [Your Feature Name] - :id: doc__feature_name - :status: draft - :safety: ASIL_D - :realizes: wp__feat_request - :tags: template - -.. attention:: - The above directive must be updated according to your Feature. - - - Modify ``document`` to be your Feature Name - - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Feature flag -============ - -To activate this feature, use the following feature flag: - -``experimental_[your_feature_name]`` - - .. note:: - The feature flag must reflect the feature name in snake_case. Further, it is prepended with ``experimental_``, as - long as the feature is not yet stable. - -Abstract -======== - -[A short (~200 word) description of the contribution being addressed.] - - -Motivation -========== - -[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] - - .. note:: - The motivation is critical for CRs that want to change the existing features or infrastructure. - It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. - Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. - CRs submissions without sufficient motivation may be rejected. - - - -Rationale -========= - -[Describe why particular design decisions were made.] - - - .. note:: - The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. - - -Specification -============= - -[Describe the requirements, architecture of any new feature.] or -[Describe the change to requirements, architecture, implementation, process, documentation, infrastructure of any change request.] - - .. note:: - A CR shall specify the stakeholder requirements as part of our platform/project. - Thereby the :need:`rl__technical_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). - - - -Backwards Compatibility -======================= - -[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] - - -Security Impact -=============== - -[How could a malicious user take advantage of this new/modified feature?] - - .. note:: - If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which security requirements are affected or has to be changed? -Could the new/modified feature enable new threat scenarios? -Could the new/modified feature enable new attack paths? -Could the new/modified feature impact functional safety? -If applicable, which additional security measures must be implemented to mitigate the risk? - - .. note:: - Use Trust Boundary, Defense in Depth Analysis and/or Security Software Critically Analysis, - Vulnerability Analysis. - [Methods will be defined later in Process area Security Analysis] - These analyses may not be available at the time of creation of the feature (request) but content will be improved iteratively. - -Safety Impact -============= - -[How could the safety be impacted by the new/modified feature?] - - .. note:: - If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - Link here to the filled out :need:`Impact Analysis Template <gd_temp__change__impact_analysis>` or copy the template in this chapter. - -Which safety requirements are affected or has to be changed? -Could the new/modified feature be a potential common cause or cascading failure initiator? -If applicable, which additional safety measures must be implemented to mitigate the risk? - - .. note:: - Use Dependency Failure Analysis and/or Safety Software Critically Analysis. - [Methods will be defined later in Process area Safety Analysis] - These analyses may not be available at the time of creation of the feature (request) but content will be improved iteratively. - -For new feature contributions: - -[What is the expected ASIL level?] - - -License Impact -============== - -[How could the copyright impacted by the license of the new contribution?] - - -How to Teach This -================= - -[How to teach users, new and experienced, how to apply the CR to their work.] - - .. note:: - For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. - - - -Rejected Ideas -============== - -[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] - - .. note:: - Throughout the discussion of a CR, various ideas will be proposed which are not accepted. - Those rejected ideas should be recorded along with the reasoning as to why they were rejected. - This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. - In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. - - - -Open Issues -=========== - -[Any points that are still being decided/discussed.] - - .. note:: - While a CR is in draft, ideas can come up which warrant further discussion. - Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. - This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. - - - -Footnotes -========= - -[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] - - -.. toctree:: - :hidden: - - requirements/index.rst - architecture/index.rst - safety_planning/index.rst - safety_analysis/fmea.rst - safety_analysis/dfa.rst diff --git a/docs/features/feature_name/requirements/index.rst b/docs/features/feature_name/requirements/index.rst deleted file mode 100644 index b5e6235f07..0000000000 --- a/docs/features/feature_name/requirements/index.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Requirements -############ - -.. document:: [Your Feature Name] Requirements - :id: doc__feature_name_requirements - :status: draft - :safety: ASIL_D - :realizes: wp__requirements__feat - :tags: template - -.. attention:: - The above directive must be updated according to your Feature. - - - Modify ``Your Feature Name`` to be your Feature Name - - Modify ``id`` to be your Feature Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -<Headlines (for the list of requirements if structuring is needed)> -=================================================================== - -.. stkh_req:: Template - :id: stkh_req__requirements__template - :reqtype: Non-Functional - :safety: ASIL_D - :rationale: Exists just for the template example - :status: invalid - - The platform shall ... - -.. attention:: - The above stakeholder requirement must be removed, it just serves as a link target for this template. - -.. feat_req:: Some Title - :id: feat_req__feature_name__some_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :satisfies: stkh_req__requirements__template - :status: invalid - - The Feature shall do xyz to the user to bring him to this condition at this time - - Note: (optional, not to be verified) - -.. aou_req:: Some Other Title - :id: aou_req__feature_name__some_other_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :status: invalid - - The Feature User shall do xyz to use the feature safely - -.. attention:: - The above directives must be updated according to your feature requirements. - - - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) - - Set the status to valid and start the review/merge process - - Add other needed requirements for your feature - -.. needextend:: "feature_name" in id - :+tags: feature_name diff --git a/docs/features/feature_name/safety_analysis/dfa.rst b/docs/features/feature_name/safety_analysis/dfa.rst deleted file mode 100644 index 8aed7eed32..0000000000 --- a/docs/features/feature_name/safety_analysis/dfa.rst +++ /dev/null @@ -1,868 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Persistency DFA -############### - -.. document:: DFA - :id: doc__persistency_dfa - :status: draft - :safety: ASIL_B - :tags: feature_persistency - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_01 - | :violation_cause: Reused software module. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_02 - | :violation_cause: Libraries. . N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_04 - | :violation_cause: Basic software. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_05 - | :violation_cause: Operating system including scheduler. Platformebene. Nicht von Middleware handlebar - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_06 - | :violation_cause: Any service stack, e.g. communication stack. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_07 - | :violation_cause: Configuration data. Return values might be falsified. - | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_09 - | :violation_cause: Execution time. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_10 - | :violation_cause: Allocated memory. Diskussion aktuell in Feature-Community. JSON kann das, sollte aber eigentlich nicht erlaubt sein - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_01 - | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) <- Checken ob das Fehlerbild überhaupt passt. 1. Satzteil nicht passen zu 2.> - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_02 - | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information. Fehlerhafte ausführung oder nichtverfügbarkeit vom feature - | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_03 - | :violation_cause: Insertion / sequence of information wie CO_01_02 - | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_04 - | :violation_cause: Corruption of information, inconsistent data wie CO_01_02 - | :mitigation: < NONE|ID from Feature Requirement> keine Erkennung - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_05 - | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_06 - | :violation_cause: Information from a sender received by only a subset of the receivers. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_07 - | :violation_cause: Blocking access to a communication channel N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_02 - | :violation_cause: Configuration data. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_03 - | :violation_cause: Constants, or variables, being global to the two software functions. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_04 - | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_05 - | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function. Unklar was das Fehlerbild ist - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_01 - | :violation_cause: Memory miss-allocation and leaks. Platformebene - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_02 - | :violation_cause: Read/Write access to memory allocated to another software element. Platformebene - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_03 - | :violation_cause: Stack/Buffer under-/overflow. Könnte passieren, ist aber unwahrscheinlich in RUST. Recursive Funktionen könnten die Ursache sein. - | :mitigation: < NONE|ID from Feature Requirement> Compilerüberwachung / AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_04 - | :violation_cause: Deadlocks. Könnten auftreten. Würde von Applikation verursacht werden. KVS kann da nichts machen - | :mitigation: < NONE|ID from Feature Requirement> AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_05 - | :violation_cause: Livelocks wie UI_01_04 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_06 - | :violation_cause: Blocking of execution. Feature is not available. - | :mitigation: < NONE|ID from Feature Requirement> AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_07 - | :violation_cause: Incorrect allocation of execution time. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_08 - | :violation_cause: Incorrect execution flow N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_09 - | :violation_cause: Incorrect synchronization between software elements N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_10 - | :violation_cause: CPU time depletion N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_11 - | :violation_cause: Memory depletion N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_12 - | :violation_cause: Other HW unavailability N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_02 - | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_03 - | :violation_cause: Same personal - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_04 - | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_05 - | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - - - - - - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_01 - | :violation_cause: Reused software modules - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_02 - | :violation_cause: Libraries - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_04 - | :violation_cause: Basic software - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_05 - | :violation_cause: Operating system including scheduler - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_06 - | :violation_cause: Any service stack, e.g. communication stack - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_07 - | :violation_cause: Configuration data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_09 - | :violation_cause: Execution time - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_10 - | :violation_cause: Allocated memory - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_01 - | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_02 - | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_03 - | :violation_cause: Insertion / sequence of information - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_04 - | :violation_cause: Corruption of information, inconsistent data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_05 - | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_06 - | :violation_cause: Information from a sender received by only a subset of the receivers - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_07 - | :violation_cause: Blocking access to a communication channel - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_02 - | :violation_cause: Configuration data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_03 - | :violation_cause: Constants, or variables, being global to the two software functions - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_04 - | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_05 - | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_01 - | :violation_cause: Memory miss-allocation and leaks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_02 - | :violation_cause: Read/Write access to memory allocated to another software element - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_03 - | :violation_cause: Stack/Buffer under-/overflow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_04 - | :violation_cause: Deadlocks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_05 - | :violation_cause: Livelocks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_06 - | :violation_cause: Blocking of execution - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_07 - | :violation_cause: Incorrect allocation of execution time - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_08 - | :violation_cause: Incorrect execution flow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_09 - | :violation_cause: Incorrect synchronization between software elements - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_10 - | :violation_cause: CPU time depletion - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_11 - | :violation_cause: Memory depletion - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_12 - | :violation_cause: Other HW unavailability - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_02 - | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_03 - | :violation_cause: Same personal - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_04 - | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_05 - | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> diff --git a/docs/features/feature_name/safety_analysis/fmea.rst b/docs/features/feature_name/safety_analysis/fmea.rst deleted file mode 100644 index 7097c89ac2..0000000000 --- a/docs/features/feature_name/safety_analysis/fmea.rst +++ /dev/null @@ -1,393 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Persistency Safety Analysis -########################### - -.. document:: Safety Analysis - :id: doc__persistency_safety_analysis - :status: draft - :safety: ASIL_B - :tags: feature_persistency - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_01 - | :failure_effect: Message is not received. User is not able to use the feature. Middleware cant be used.A - | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_02 - | :failure_effect: message received too late. User might not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_03 - | :failure_effect: message received too early. No impact / feature reacts only if triggered on the trigger. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_04 - | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost). N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_05 - | :failure_effect: message is corrupted. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_06 - | :failure_effect: message is not sent. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_07 - | :failure_effect: message is unintended sent. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: CO_01_01 - | :failure_effect: minimum constraint boundary is violated. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: CO_01_02 - | :failure_effect: maximum constraint boundary is violated. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_01 - | :failure_effect: Process calculates wrong result(s). Feature is not usable. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_02 - | :failure_effect: processing too slow. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_03 - | :failure_effect: processing too fast. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_04 - | :failure_effect: loss of execution. User is not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_05 - | :failure_effect: processing changes to arbitrary process. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_06 - | :failure_effect: processing is not complete (infinite loop). User is not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - - - - - - - - - - - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_01 - | :failure_effect: message is not received - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_02 - | :failure_effect: message received too late - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_03 - | :failure_effect: message received too early - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_04 - | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_05 - | :failure_effect: message is corrupted - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_06 - | :failure_effect: message is not sent - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_07 - | :failure_effect: message is unintended sent - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: CO_01_01 - | :failure_effect: minimum constraint boundary is violated - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: CO_01_02 - | :failure_effect: maximum constraint boundary is violated - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_01 - | :failure_effect: Process calculates wrong result(s) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_02 - | :failure_effect: processing too slow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_03 - | :failure_effect: processing too fast - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_04 - | :failure_effect: loss of execution - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_05 - | :failure_effect: processing changes to arbitrary process - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_06 - | :failure_effect: processing is not complete (infinite loop) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> diff --git a/docs/features/feature_name/safety_planning/index.rst b/docs/features/feature_name/safety_planning/index.rst deleted file mode 100644 index c45fd37406..0000000000 --- a/docs/features/feature_name/safety_planning/index.rst +++ /dev/null @@ -1,130 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _feature_safety_wp_template: - -Feature Safety Planning -======================= - -.. list-table:: Feature <feature> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP status - - * - :need:`wp__feat_request` - - :need:`gd_temp__change__feature_request` - - :ndf:`copy('status', need_id='gd_temp__change__feature_request')` - - https://github.com/eclipse-score/score/issues/760 - - :need:`doc__feature_name` - - :ndf:`copy('status', need_id='doc__feature_name')` - - * - :need:`wp__requirements__feat` - - :need:`gd_temp__req__feat_req` - - :ndf:`copy('status', need_id='gd_temp__req__feat_req')` - - https://github.com/eclipse-score/score/issues/960 - - :doc:`../requirements/index` - - see below - - * - :need:`wp__requirements__feat_aou` - - :need:`gd_temp__req__aou_req` - - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` - - https://github.com/eclipse-score/score/issues/960 - - :doc:`../requirements/index` - - see below - - * - :need:`wp__feature_arch` - - :need:`gd_temp__arch__feature` - - :ndf:`copy('status', need_id='gd_temp__arch__feature')` - - https://github.com/eclipse-score/score/issues/1020 - - :doc:`../architecture/index` - - see below - - * - :need:`wp__feature_safety_analysis` - - <link to process> - - <automated> - - https://github.com/eclipse-score/score/issues/965 - - :doc:`../safety_analysis/doc__persistency_safety_analysis` - - <automated> - - * - :need:`wp__feature_dfa` - - <Link to process> - - <Process status> - - https://github.com/eclipse-score/score/issues/965 - - :doc:`../safety_analysis/doc__persistency_dfa` - - <automated> - - * - :need:`wp__requirements__inspect` - - :need:`gd_chklst__req__inspection` - - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__sw_arch_verification` - - :need:`gd_chklst__arch__inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__verification__feat_int_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` - - <link to issue> - - https://github.com/eclipse-score/score/issues/964 - - <automated> - -.. attention:: - The above table must be updated according to your feature safety planning. - - - Create and link the issues to plan the work products (according to :need:`gd_guidl__saf_plan_definitions`) - - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`gd_guidl__saf_package`) - -Feature Requirements Status ---------------------------- - -.. needtable:: - :style: table - :types: feat_req - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title - -Feature AoU Status ------------------- - -.. needtable:: - :style: table - :types: aou_req - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title - -Feature Architecture Status ---------------------------- - -.. needtable:: - :style: table - :types: feat_arc_sta; feat_arc_dyn - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title diff --git a/docs/features/persistency/architecture/index.rst b/docs/features/persistency/architecture/index.rst index a56e5daf3b..3495f1fa12 100644 --- a/docs/features/persistency/architecture/index.rst +++ b/docs/features/persistency/architecture/index.rst @@ -45,7 +45,7 @@ Static Architecture :security: YES :safety: ASIL_B :includes: logic_arc_int__persistency__interface - :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values + :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value :status: valid .. uml:: _assets/kvs_static_view.puml @@ -83,7 +83,7 @@ Dynamic Architecture :id: feat_arc_dyn__persistency__read_key :security: YES :safety: ASIL_B - :fulfils: feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values,feat_req__persistency__default_values,feat_req__persistency__default_value_get + :fulfils: feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value,feat_req__persistency__default_values,feat_req__persistency__default_value_get :status: valid .. uml:: _assets/kvs_dyn_read_data_key.puml @@ -101,7 +101,7 @@ Dynamic Architecture :id: feat_arc_dyn__persistency__write_key :security: YES :safety: ASIL_B - :fulfils: feat_req__persistency__supported_datatypes_keys,feat_req__persistency__supported_datatypes_values + :fulfils: feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value :status: valid .. uml:: _assets/kvs_dyn_write_data_key.puml diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index 76e8ac97a6..6111a0fa9d 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -24,6 +24,9 @@ Key-Value-Storage .. toctree:: architecture/index.rst requirements/index.rst + safety_analysis/fmea.rst + safety_analysis/dfa.rst + safety_planning/index.rst Feature flag diff --git a/docs/modules/persistency/docs/safety_mgt/index.rst b/docs/modules/persistency/docs/safety_mgt/index.rst index 04718ba355..fa3a7ff35c 100644 --- a/docs/modules/persistency/docs/safety_mgt/index.rst +++ b/docs/modules/persistency/docs/safety_mgt/index.rst @@ -17,7 +17,3 @@ Safety Management .. toctree:: :titlesonly: - - module_safety_plan - module_safety_plan_fdr - module_safety_package_fdr diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst deleted file mode 100644 index f841547bb8..0000000000 --- a/docs/modules/persistency/docs/safety_mgt/module_safety_package_fdr.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Safety Package Formal Review Report -=================================== - -.. note:: Document header - -.. document:: [Your Module Name] Safety Package Formal Review - :id: doc__module_name_safety_package_fdr - :status: draft - :safety: ASIL_D - :realizes: wp__fdr_reports - :tags: template - -.. attention:: - The above directive must be updated according to your Module. - - - Modify ``Your Module Name`` to be your Module Name - - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``safety_package_fdr`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - - -**1. Purpose** - -The purpose of this review checklist is to report status of the formal review for the safety package. - -**2. Checklist** - -.. list-table:: Safety Package Checklist - :header-rows: 1 - - * - Id - - Safety package activity - - Compliant to ISO 26262? - - Comment - - * - 1 - - Is a safety package provided which matches the safety plan (i.e. all planned workproducts referenced)? - - [YES | NO ] - - <Rationale for result> - - * - 2 - - Is the argument how functional safety is achieved, provided in the safety package, plausible and sufficient? - - NO - - The argument is intentionally not provided by S-CORE. - - * - 3 - - Are the referenced work products available? - - [YES | NO ] - - <Rationale for result> - - * - 4 - - Are the referenced work products in released state, including the process safety audit? - - [YES | NO ] - - <Rationale for result> - - * - 5 - - If safety related deviations from the process or safety concept are documented, are these argued understandably? - - [YES | NO ] - - <Rationale for result> diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst deleted file mode 100644 index c07e3fe5dc..0000000000 --- a/docs/modules/persistency/docs/safety_mgt/module_safety_plan.rst +++ /dev/null @@ -1,357 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Module Safety Plan -****************** - -.. note:: Document header - -.. document:: [Your Module Name] Safety Plan - :id: doc__module_name_safety_plan - :status: draft - :safety: ASIL_D - :realizes: wp__module_safety_plan - :tags: template - -.. attention:: - The above directive must be updated according to your Module. - - - Modify ``Your Module Name`` to be your Module Name - - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``safety_plan`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - - -Functional Safety Management Context -==================================== - -This Safety Plan adds to the :ref:`process_safety_management` all the module development relevant workproducts needed for ISO 26262 conformity. - -Functional Safety Management Scope -================================== - -This Safety Plan's scope is a SW module of the SW platform <link to module documentation in platform/modules/<modulename>/index.rst>. -The module consists of one or more SW components and will be qualified as a SEooC. - -Functional Safety Management Roles -================================== - -+---------------------------+--------------------------------------------------------+ -| Safety Manager | <link to Module's Safety Manager assignment or name> | -+---------------------------+--------------------------------------------------------+ -| Project Manager | <link to Module's Project Manager assignment or name> | -+---------------------------+--------------------------------------------------------+ - -Tailoring -========= - -Additional to the tailoring in the SW platform project as defined in the :ref:`process_safety_management` we define here the additional tailoring on module level. - -- Excluded for this module are additionally the following workproducts (and their related requirements): - - <ISO 26262 reference>: <workproduct/requirement> - <Argumentation why it is not needed or replaced by another workproduct or activity.> - -Functional Safety Module Workproducts -===================================== - -One set of workproducts for the module and one set for each component of the module: - -Module Workproducts List ------------------------- - -.. list-table:: Module Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP status - - * - :need:`wp__module_safety_plan` - - :need:`gd_guidl__saf_plan_definitions` - - :ndf:`copy('status', need_id='gd_guidl__saf_plan_definitions')` - - <Link to issue> - - this document - - see above - - * - :need:`wp__module_safety_package` - - :need:`gd_guidl__saf_package` - - :ndf:`copy('status', need_id='gd_guidl__saf_package')` - - <Link to issue> - - this document (including the linked documentation) - - see above (and below) - - * - :need:`wp__fdr_reports` (module Safety Plan) - - :need:`gd_chklst__safety_plan` - - :ndf:`copy('status', need_id='gd_chklst__safety_plan')` - - <Link to issue> - - :need:`doc__module_name_safety_plan_fdr` - - :ndf:`copy('status', need_id='doc__module_name_safety_plan_fdr')` - - * - :need:`wp__fdr_reports` (module Safety Package) - - :need:`gd_chklst__safety_package` - - :ndf:`copy('status', need_id='gd_chklst__safety_package')` - - <Link to issue> - - :need:`doc__module_name_safety_package_fdr` - - :ndf:`copy('status', need_id='doc__module_name_safety_package_fdr')` - - * - :need:`wp__fdr_reports` (module's Safety Analyses & DFA) - - Safety Analysis FDR tbd - - <automated> - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__audit_report` - - performed by external experts - - n/a - - <Link to issue> - - <Link to WP> - - <WP status (manual)> - - * - :need:`wp__module_sw_build_config` - - :need:`SCORE_doc__software_development_plan` - - :ndf:`copy('status', need_id='SCORE_doc__software_development_plan')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__module_safety_manual` - - :need:`gd_temp__safety_manual` - - :ndf:`copy('status', need_id='gd_temp__safety_manual')` - - <Link to issue> - - :need:`doc__module_name_safety_manual` - - :ndf:`copy('status', need_id='doc__module_name_safety_manual')` - - * - :need:`wp__verification__module_ver_report` - - :need:`gd_temp__mod_ver_report` - - :ndf:`copy('status', need_id='gd_temp__mod_ver_report')` - - <Link to issue> - - :need:`doc__module_name_verification_report` - - :ndf:`copy('status', need_id='doc__module_name_verification_report')` - - * - :need:`wp__module_sw_release_note` - - :need:`gd_temp__rel__mod_rel_note` - - :ndf:`copy('status', need_id='gd_temp__rel__mod_rel_note')` - - <Link to issue> - - :need:`doc__module_name_release_note` - - :ndf:`copy('status', need_id='doc__module_name_release_note')` - -Component <name> Workproducts List ----------------------------------- - -.. list-table:: Component <name> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP/doc status - - * - :need:`wp__requirements__comp` - - :need:`gd_temp__req__comp_req` - - :ndf:`copy('status', need_id='gd_temp__req__comp_req')` - - <Link to issue> - - :need:`doc__component_name_requirements` - - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below - - * - :need:`wp__requirements__comp_aou` - - :need:`gd_temp__req__aou_req` - - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` - - <Link to issue> - - :need:`doc__component_name_requirements` - - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below - - * - :need:`wp__hsi` - - <Link to process> - - <automated> - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__requirements__inspect` - - :need:`gd_chklst__req__inspection` - - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__component_arch` - - :need:`gd_temp__arch__comp` - - :ndf:`copy('status', need_id='gd_temp__arch__comp')` - - <Link to issue> - - :need:`doc__component_name_architecture` - - doc :ndf:`copy('status', need_id='doc__component_name_architecture')` & WP below - - * - :need:`wp__sw_arch_verification` - - :need:`gd_chklst__arch__inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__sw_component_safety_analysis` - - <Link to process> - - <automated> - - <Link to issue> - - :need:`doc__component_name_fmea` - - doc :ndf:`copy('status', need_id='doc__component_name_fmea')` & WP below - - * - :need:`wp__sw_component_dfa` - - <Link to process> - - <automated> - - <Link to issue> - - :need:`doc__component_name_dfa` - - doc :ndf:`copy('status', need_id='doc__component_name_dfa')` & WP below - - * - :need:`wp__sw_implementation` - - :need:`gd_guidl__implementation` - - :ndf:`copy('status', need_id='gd_guidl__implementation')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__verification__sw_unit_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__sw_implementation_inspection` - - :need:`gd_chklst__impl_inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__impl_inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__verification__comp_int_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__sw_component_class` - - :need:`gd_guidl__component_classification` - - :ndf:`copy('status', need_id='gd_guidl__component_classification')` - - <Link to issue> - - :need:`doc__component_name_comp_class` - - :ndf:`copy('status', need_id='doc__component_name_comp_class')` - -Note: In case the component is a new development, :need:`wp__sw_component_class` shall be removed from the above list (and also from the folders). -In case an OSS element is used in the module, part 6 has to be filled out. - -OSS (sub-)component qualification plan -====================================== - -For the selected OSS component the following workproducts will be implemented (and why): - -If the OSS element is classified as a - - component, then the below table shall match the above, adding the reasoning for tailoring of work products according to the OSS component classification. - - lower level component, then no workproducts additional to the component’s will be planned and activities below are part of the component’s issues. - -.. list-table:: OSS (sub-)component <name> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to issue - - Reasoning for tailoring - - * - :need:`wp__requirements__comp` - - <Link to issue> - - Always needed (for Q and QR classification) and also improves process Id 2 - - * - :need:`wp__requirements__comp_aou` - - <Link to issue> - - Always needed (for Q and QR classification) and also improves process Id 5 - - * - :need:`wp__hsi` - - n/a - - OSS needing special HW is an extreme exception. - - * - :need:`wp__requirements__inspect` - - n/a - - Checklist used in Pull Request Review - - * - :need:`wf__cr_mt_comparch` - - <Link to issue> - - <Reasoning for tailoring, needed for example in case of deficits in process Id 3&4 and complexity Ids 1&4> - - * - :need:`wp__sw_component_safety_analysis` - - <Link to issue> - - <Reasoning for tailoring, could help arguing too high cyclomatic complexity covered by safety mechanisms> - - * - :need:`wp__sw_arch_verification` - - <Link to issue> - - <Reasoning for tailoring, needed if also wf__cr_mt_comparch is required> - - * - :need:`wp__sw_implementation` - - n/a - - If source code is modified, this is not a OSS qualification any more. - - * - :need:`wp__verification__sw_unit_test` - - <Link to issue> - - <Reasoning for tailoring, can improve deficits in process Id 6 and complexity Id 3> - - * - :need:`wp__sw_implementation_inspection` - - <Link to issue> - - <Reasoning for tailoring, can improve deficits in process Id 6 and complexity Id 2> - - * - :need:`wp__verification__comp_int_test` - - <Link to issue> - - Always needed (for Q and QR classification) - - * - :need:`wp__sw_component_class` - - <Link to issue> - - Always needed as basis for tailoring. - -Work Product Status (for Safety Package) -======================================== - -Component Requirements Status ------------------------------ - -.. needtable:: - :style: table - :types: comp_req - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title - -Component AoU Status --------------------- - -.. needtable:: - :style: table - :types: aou_req - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title - -Component Architecture Status ------------------------------ - -.. needtable:: - :style: table - :types: comp_arc_sta; comp_arc_dyn - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title diff --git a/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst b/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst deleted file mode 100644 index 2ec526b291..0000000000 --- a/docs/modules/persistency/docs/safety_mgt/module_safety_plan_fdr.rst +++ /dev/null @@ -1,348 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Module Safety Plan -****************** - -.. note:: Document header - -.. document:: Persistency Safety Plan - :id: doc__persistency_safety_plan - :status: draft - :safety: ASIL_B - :realizes: wp__module_safety_plan - :tags: feature_persistency - -Functional Safety Management Context -==================================== - -This Safety Plan adds to the :ref:`process_safety_management` all the module development relevant workproducts needed for ISO 26262 conformity. - -Functional Safety Management Scope -================================== - -This Safety Plan's scope is a SW module of the SW platform :doc:`../docs/features/persistency/index`. -The module consists of one or more SW components and will be qualified as a SEooC. - -Functional Safety Management Roles -================================== - -+---------------------------+-------------------------------------------------------------------------------------+ -| Safety Manager | Volker Häussler `Issue #963 <https://github.com/eclipse-score/score/issues/952>`_ | -+---------------------------+-------------------------------------------------------------------------------------+ -| Project Manager | Lars Bauhofer `Issue #963 <https://github.com/eclipse-score/score/issues/952>`_ | -+---------------------------+-------------------------------------------------------------------------------------+ - -Tailoring -========= - -Additional to the tailoring in the SW platform project as defined in the :ref:`process_safety_management` we define here the additional tailoring on module level. - -- Excluded for this module are additionally the following workproducts (and their related requirements): - - none - -Functional Safety Module Workproducts -===================================== - -One set of workproducts for the module and one set for each component of the module: - -Module Workproducts List ------------------------- - -.. list-table:: Module Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP status - - * - :need:`wp__module_safety_plan` - - :need:`gd_guidl__saf_plan_definitions` - - :ndf:`copy('status', need_id='gd_guidl__saf_plan_definitions')` - - `Issue #963 <https://github.com/eclipse-score/score/issues/963>`_ - - this document - - see above - - * - :need:`wp__module_safety_package` - - :need:`gd_guidl__saf_package` - - :ndf:`copy('status', need_id='gd_guidl__saf_package')` - - `Issue #963 <https://github.com/eclipse-score/score/issues/963>`_ - - this document (including the linked documentation) - - see above (and below) - - * - :need:`wp__fdr_reports` (module Safety Plan) - - :need:`gd_chklst__safety_plan` - - :ndf:`copy('status', need_id='gd_chklst__safety_plan')` - - `Issue #963 <https://github.com/eclipse-score/score/issues/963>`_ - - :need:`doc__module_name_safety_plan_fdr` - - :ndf:`copy('status', need_id='doc__module_name_safety_plan_fdr')` - - * - :need:`wp__fdr_reports` (module Safety Package) - - :need:`gd_chklst__safety_package` - - :ndf:`copy('status', need_id='gd_chklst__safety_package')` - - `Issue #963 <https://github.com/eclipse-score/score/issues/963>`_ - - :need:`doc__module_name_safety_package_fdr` - - :ndf:`copy('status', need_id='doc__module_name_safety_package_fdr')` - - * - :need:`wp__fdr_reports` (module's Safety Analyses & DFA) - - Safety Analysis FDR tbd - - <automated> - - `Issue #965 <https://github.com/eclipse-score/score/issues/965>`_ - - <Link to WP> - - <automated> - - * - :need:`wp__audit_report` - - performed by external experts - - n/a - - <Link to issue> - - <Link to WP> - - <WP status (manual)> - - * - :need:`wp__module_sw_build_config` - - :need:`SCORE_doc__software_development_plan` - - :ndf:`copy('status', need_id='SCORE_doc__software_development_plan')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__module_safety_manual` - - :need:`gd_temp__safety_manual` - - :ndf:`copy('status', need_id='gd_temp__safety_manual')` - - <Link to issue> - - :need:`doc__module_name_safety_manual` - - :ndf:`copy('status', need_id='doc__module_name_safety_manual')` - - * - :need:`wp__verification__module_ver_report` - - :need:`gd_temp__mod_ver_report` - - :ndf:`copy('status', need_id='gd_temp__mod_ver_report')` - - <Link to issue> - - :need:`doc__module_name_verification_report` - - :ndf:`copy('status', need_id='doc__module_name_verification_report')` - - * - :need:`wp__module_sw_release_note` - - :need:`gd_temp__rel__mod_rel_note` - - :ndf:`copy('status', need_id='gd_temp__rel__mod_rel_note')` - - <Link to issue> - - :need:`doc__module_name_release_note` - - :ndf:`copy('status', need_id='doc__module_name_release_note')` - -Component <name> Workproducts List ----------------------------------- - -.. list-table:: Component <name> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP/doc status - - * - :need:`wp__requirements__comp` - - :need:`gd_temp__req__comp_req` - - :ndf:`copy('status', need_id='gd_temp__req__comp_req')` - - <Link to issue> - - :need:`doc__component_name_requirements` - - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below - - * - :need:`wp__requirements__comp_aou` - - :need:`gd_temp__req__aou_req` - - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` - - <Link to issue> - - :need:`doc__component_name_requirements` - - doc :ndf:`copy('status', need_id='doc__component_name_requirements')` & WP below - - * - :need:`wp__hsi` - - <Link to process> - - <automated> - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__requirements__inspect` - - :need:`gd_chklst__req__inspection` - - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__component_arch` - - :need:`gd_temp__arch__comp` - - :ndf:`copy('status', need_id='gd_temp__arch__comp')` - - <Link to issue> - - :need:`doc__component_name_architecture` - - doc :ndf:`copy('status', need_id='doc__component_name_architecture')` & WP below - - * - :need:`wp__sw_arch_verification` - - :need:`gd_chklst__arch__inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__sw_component_safety_analysis` - - <Link to process> - - <automated> - - <Link to issue> - - :need:`doc__component_name_fmea` - - doc :ndf:`copy('status', need_id='doc__component_name_fmea')` & WP below - - * - :need:`wp__sw_component_dfa` - - <Link to process> - - <automated> - - <Link to issue> - - :need:`doc__component_name_dfa` - - doc :ndf:`copy('status', need_id='doc__component_name_dfa')` & WP below - - * - :need:`wp__sw_implementation` - - :need:`gd_guidl__implementation` - - :ndf:`copy('status', need_id='gd_guidl__implementation')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__verification__sw_unit_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__sw_implementation_inspection` - - :need:`gd_chklst__impl_inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__impl_inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`wp__verification__comp_int_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` - - <Link to issue> - - <Link to WP> - - <automated> - - * - :need:`wp__sw_component_class` - - :need:`gd_guidl__component_classification` - - :ndf:`copy('status', need_id='gd_guidl__component_classification')` - - <Link to issue> - - :need:`doc__component_name_comp_class` - - :ndf:`copy('status', need_id='doc__component_name_comp_class')` - -Note: In case the component is a new development, :need:`wp__sw_component_class` shall be removed from the above list (and also from the folders). -In case an OSS element is used in the module, part 6 has to be filled out. - -OSS (sub-)component qualification plan -====================================== - -For the selected OSS component the following workproducts will be implemented (and why): - -If the OSS element is classified as a - - component, then the below table shall match the above, adding the reasoning for tailoring of work products according to the OSS component classification. - - lower level component, then no workproducts additional to the component’s will be planned and activities below are part of the component’s issues. - -.. list-table:: OSS (sub-)component <name> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to issue - - Reasoning for tailoring - - * - :need:`wp__requirements__comp` - - <Link to issue> - - Always needed (for Q and QR classification) and also improves process Id 2 - - * - :need:`wp__requirements__comp_aou` - - <Link to issue> - - Always needed (for Q and QR classification) and also improves process Id 5 - - * - :need:`wp__hsi` - - n/a - - OSS needing special HW is an extreme exception. - - * - :need:`wp__requirements__inspect` - - n/a - - Checklist used in Pull Request Review - - * - :need:`wf__cr_mt_comparch` - - <Link to issue> - - <Reasoning for tailoring, needed for example in case of deficits in process Id 3&4 and complexity Ids 1&4> - - * - :need:`wp__sw_component_safety_analysis` - - <Link to issue> - - <Reasoning for tailoring, could help arguing too high cyclomatic complexity covered by safety mechanisms> - - * - :need:`wp__sw_arch_verification` - - <Link to issue> - - <Reasoning for tailoring, needed if also wf__cr_mt_comparch is required> - - * - :need:`wp__sw_implementation` - - n/a - - If source code is modified, this is not a OSS qualification any more. - - * - :need:`wp__verification__sw_unit_test` - - <Link to issue> - - <Reasoning for tailoring, can improve deficits in process Id 6 and complexity Id 3> - - * - :need:`wp__sw_implementation_inspection` - - <Link to issue> - - <Reasoning for tailoring, can improve deficits in process Id 6 and complexity Id 2> - - * - :need:`wp__verification__comp_int_test` - - <Link to issue> - - Always needed (for Q and QR classification) - - * - :need:`wp__sw_component_class` - - <Link to issue> - - Always needed as basis for tailoring. - -Work Product Status (for Safety Package) -======================================== - -Component Requirements Status ------------------------------ - -.. needtable:: - :style: table - :types: comp_req - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title - -Component AoU Status --------------------- - -.. needtable:: - :style: table - :types: aou_req - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title - -Component Architecture Status ------------------------------ - -.. needtable:: - :style: table - :types: comp_arc_sta; comp_arc_dyn - :tags: component_name - :columns: id;status;tags - :colwidths: 25,25,25 - :sort: title diff --git a/docs/modules/persistency/json/docs/architecture/index.rst b/docs/modules/persistency/json/docs/architecture/index.rst deleted file mode 100644 index 731769dd5b..0000000000 --- a/docs/modules/persistency/json/docs/architecture/index.rst +++ /dev/null @@ -1,130 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _component_architecture_template: - -Component Architecture -====================== - -.. document:: [Your Component Name] Architecture - :id: doc__component_name_architecture - :status: draft - :safety: ASIL_D - :realizes: wp__component_arch - :tags: template - -.. attention:: - The above directive must be updated according to your needs. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Overview --------- -Brief summary - -Requirements Linked to Component Architecture ---------------------------------------------- - -.. code-block:: none - - .. needtable:: Overview of Component Requirements - :style: table - :columns: title;id - :filter: search("comp_arch_sta__archdes$", "fulfils_back") - :colwidths: 70,30 - -Description ------------ - -General Description - -Design Decisions - -Design Constraints - -Rationale Behind Architecture Decomposition -******************************************* -mandatory: a motivation for the decomposition or reason for not further splitting it into sub components. - -.. note:: Common decisions across components / cross cutting concepts is at the higher level. - -Static Architecture -------------------- - -The components are designed to cover the expectations from the feature architecture -(i.e. if already exists a definition it should be taken over and enriched). - -.. comp_arc_sta:: Component Name (Static View) - :id: comp_arc_sta__component_name__static_view - :security: YES - :safety: ASIL_D - :status: invalid - :implements: logic_arc_int__feature_name__interface_name - :fulfils: comp_req__component_name__some_title - :includes: comp_arc_sta__component_name__2 - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_component(need(), needs) }} - -Dynamic Architecture --------------------- - -.. comp_arc_dyn:: Dynamic View - :id: comp_arc_dyn__component_name__dynamic_view - :security: YES - :safety: ASIL_D - :status: invalid - :fulfils: comp_req__component_name__some_title - - put here a sequence diagram - - -Interfaces ----------- - -.. code-block:: rst - - .. real_arc_int:: <Title> - :id: real_arc_int__<component>__<Title> - :security: <YES|NO> - :safety: <QM|ASIL_B|ASIL_D> - :fulfils: <link to component requirement id> - :language: cpp - -Lower Level Components ----------------------- - -.. comp_arc_sta:: Component Name 2 - :id: comp_arc_sta__component_name__2 - :status: invalid - :safety: ASIL_D - :security: YES - :implements: logic_arc_int__feature_name__interface_name - - no architecture but detailed design - -.. note:: - Architecture can be split into multiple files. At component level the public interfaces to be used by the user and tester to be shown. - -.. attention:: - The above directives must be updated according to your component architecture. - - - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) - - Set the status to valid and start the review/merge process diff --git a/docs/modules/persistency/json/docs/index.rst b/docs/modules/persistency/json/docs/index.rst index aef22a742b..d664d2b17c 100644 --- a/docs/modules/persistency/json/docs/index.rst +++ b/docs/modules/persistency/json/docs/index.rst @@ -12,17 +12,17 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _component_template: +.. _component_PersistencyJson: Tiny JSON ######### .. note:: Document header -.. document:: [Your Component Name] - :id: doc__component_name +.. document:: Persistency JSON + :id: doc__PersistencyJson :status: draft - :safety: ASIL_D + :safety: ASIL_B :realizes: wp__cmpt_request :tags: template @@ -173,8 +173,4 @@ Footnotes .. toctree:: :hidden: - requirements/index.rst - architecture/index.rst - safety_analysis/fmea.rst - safety_analysis/dfa.rst component_classification.rst diff --git a/docs/modules/persistency/json/docs/requirements/index.rst b/docs/modules/persistency/json/docs/requirements/index.rst deleted file mode 100644 index 9e0d6d7b6f..0000000000 --- a/docs/modules/persistency/json/docs/requirements/index.rst +++ /dev/null @@ -1,72 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Requirements -############ - -.. document:: [Your Component Name] Requirements - :id: doc__component_name_requirements - :status: draft - :safety: ASIL_D - :realizes: wp__requirements__comp - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_requirements`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -<Headlines (for the list of requirements if structuring is needed)> -=================================================================== - -.. comp_req:: Some Title - :id: comp_req__component_name__some_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :satisfies: feat_req__feature_name__some_title - :status: invalid - - The Component shall do xyz to another component to bring it to this condition at this time - - Note: (optional, not to be verified) - -.. attention:: - The above directive must be updated according to your component requirements. - - - Replace the example content by the real content for your first requirement - - Set the status to valid and start the review/merge process - - Add other needed requirements for your component - -.. aou_req:: Next Title - :id: aou_req__component_name__next_title - :reqtype: Process - :security: YES - :safety: ASIL_D - :status: invalid - - The Component User shall do xyz to use the component safely - -.. attention:: - The above directives must be updated according to your feature requirements. - - - Replace the example content by the real content for your first requirement (according to :need:`gd_guidl__req__engineering`) - - Set the status to valid and start the review/merge process - - Add other needed requirements for your feature - -.. needextend:: "component_name" in id - :+tags: component_name diff --git a/docs/modules/persistency/json/docs/safety_analysis/dfa.rst b/docs/modules/persistency/json/docs/safety_analysis/dfa.rst deleted file mode 100644 index 1626d6304c..0000000000 --- a/docs/modules/persistency/json/docs/safety_analysis/dfa.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - - -Dependent Failure Analysis -========================== - -.. document:: [Your Component Name] DFA - :id: doc__component_name_dfa - :status: draft - :safety: ASIL_D - :realizes: wp__sw_component_dfa - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_dfa`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Dependent Failure Intitiators ------------------------------ - -.. code-block:: rst - - .. comp_saf_dfa:: <Element descriptor> - :id: comp_saf_DFA__<Component>__<Element descriptor> - :violation_id: <ID from Dependent Failure Initiators list :need:`gd_guidl__dfi`> - :violation_effect: <Effect caused by the initiator (leading to a violation of a safety goal)> - :verifies: <ID from Component Architecture> - :mitigated_by: < NONE|ID from Component Requirement> - :sufficient: <yes|no> - :argument: <text to argument why measure is sufficient> - :status: <valid|invalid> - -.. attention:: - The above directive must be updated according to your component DFA. - - - Remove the ``code-block`` - - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/json/docs/safety_analysis/fmea.rst b/docs/modules/persistency/json/docs/safety_analysis/fmea.rst deleted file mode 100644 index 319c63d4ef..0000000000 --- a/docs/modules/persistency/json/docs/safety_analysis/fmea.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - - -Safety Analysis : FMEA -====================== - -.. document:: [Your Component Name] FMEA - :id: doc__component_name_fmea - :status: draft - :safety: ASIL_D - :realizes: wp__sw_component_safety_analysis - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_fmea`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Failure Mode List ------------------ - -.. code-block:: rst - - .. comp_saf_fmea:: <Element descriptor> - :id: comp_saf_FMEA__<Component>__<Element descriptor> - :failure_mode: <ID from fault model :need:`gd_guidl__fault_models`> - :failure_effect: <Effect caused by the failure (leading to a violation of a safety goal)> - :verifies: <ID from Component Architecture> - :mitigated_by: < NONE|ID from Component Requirement> - :sufficient: <yes|no> - :argument: <text to argument why measure is sufficient> - :status: <valid|invalid> - -.. attention:: - The above directive must be updated according to your component FMEA. - - - Remove the ``code-block`` - - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/kvs/docs/architecture/index.rst b/docs/modules/persistency/kvs/docs/architecture/index.rst index 731769dd5b..0dc52ce7fb 100644 --- a/docs/modules/persistency/kvs/docs/architecture/index.rst +++ b/docs/modules/persistency/kvs/docs/architecture/index.rst @@ -12,15 +12,15 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _component_architecture_template: +.. _component_architecture_PersistencyKvs: Component Architecture ====================== -.. document:: [Your Component Name] Architecture - :id: doc__component_name_architecture +.. document:: Persistency KVS Architecture + :id: doc__persistency_kvs_architecture :status: draft - :safety: ASIL_D + :safety: ASIL_B :realizes: wp__component_arch :tags: template @@ -69,13 +69,13 @@ The components are designed to cover the expectations from the feature architect (i.e. if already exists a definition it should be taken over and enriched). .. comp_arc_sta:: Component Name (Static View) - :id: comp_arc_sta__component_name__static_view + :id: comp_arc_sta__persistency_kvs__static_view :security: YES :safety: ASIL_D :status: invalid :implements: logic_arc_int__feature_name__interface_name - :fulfils: comp_req__component_name__some_title - :includes: comp_arc_sta__component_name__2 + :fulfils: comp_req__persistency_kvs__some_title + :includes: comp_arc_sta__persistency_kvs__2 .. needarch:: :scale: 50 @@ -87,11 +87,11 @@ Dynamic Architecture -------------------- .. comp_arc_dyn:: Dynamic View - :id: comp_arc_dyn__component_name__dynamic_view + :id: comp_arc_dyn__persistency_kvs__dynamic_view :security: YES :safety: ASIL_D :status: invalid - :fulfils: comp_req__component_name__some_title + :fulfils: comp_req__persistency_kvs__some_title put here a sequence diagram @@ -112,7 +112,7 @@ Lower Level Components ---------------------- .. comp_arc_sta:: Component Name 2 - :id: comp_arc_sta__component_name__2 + :id: comp_arc_sta__persistency_kvs__2 :status: invalid :safety: ASIL_D :security: YES diff --git a/docs/modules/persistency/kvs/docs/index.rst b/docs/modules/persistency/kvs/docs/index.rst index d57f2f1674..6654c1f042 100644 --- a/docs/modules/persistency/kvs/docs/index.rst +++ b/docs/modules/persistency/kvs/docs/index.rst @@ -12,17 +12,17 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _component_template: +.. _component_PersistencyKvs: KVS (Key Value Store) ##################### .. note:: Document header -.. document:: [Your Component Name] - :id: doc__component_name +.. document:: Persistency KVS + :id: doc__PersistencyKvs :status: draft - :safety: ASIL_D + :safety: ASIL_B :realizes: wp__cmpt_request :tags: template diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst b/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst index 1626d6304c..be4e82b4b1 100644 --- a/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst +++ b/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst @@ -16,10 +16,10 @@ Dependent Failure Analysis ========================== -.. document:: [Your Component Name] DFA - :id: doc__component_name_dfa - :status: draft - :safety: ASIL_D +.. document:: KVS DFA + :id: doc__kvs_dfa + :status: valid + :safety: ASIL_B :realizes: wp__sw_component_dfa :tags: template diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst b/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst index 319c63d4ef..7a5c4eccc8 100644 --- a/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst +++ b/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst @@ -16,10 +16,10 @@ Safety Analysis : FMEA ====================== -.. document:: [Your Component Name] FMEA - :id: doc__component_name_fmea - :status: draft - :safety: ASIL_D +.. document:: KVS FMEA + :id: doc__kvs_fmea + :status: valid + :safety: ASIL_B :realizes: wp__sw_component_safety_analysis :tags: template From cd08447d134dbb5148305388106c6968b5c3f811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20H=C3=A4ussler?= <volker.haeussler@qorix.ai> Date: Wed, 4 Jun 2025 10:02:34 +0200 Subject: [PATCH 033/102] process: fix errors that documentation is buildable --- docs/features/persistency/architecture/index.rst | 6 +++--- docs/modules/persistency/json/docs/index.rst | 2 +- .../persistency/kvs/docs/architecture/index.rst | 16 ++++++++-------- docs/modules/persistency/kvs/docs/index.rst | 2 +- .../persistency/kvs/docs/requirements/index.rst | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/features/persistency/architecture/index.rst b/docs/features/persistency/architecture/index.rst index 3495f1fa12..21ee05d945 100644 --- a/docs/features/persistency/architecture/index.rst +++ b/docs/features/persistency/architecture/index.rst @@ -45,7 +45,7 @@ Static Architecture :security: YES :safety: ASIL_B :includes: logic_arc_int__persistency__interface - :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value + :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value :status: valid .. uml:: _assets/kvs_static_view.puml @@ -83,7 +83,7 @@ Dynamic Architecture :id: feat_arc_dyn__persistency__read_key :security: YES :safety: ASIL_B - :fulfils: feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value,feat_req__persistency__default_values,feat_req__persistency__default_value_get + :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value,feat_req__persistency__default_values,feat_req__persistency__default_value_get :status: valid .. uml:: _assets/kvs_dyn_read_data_key.puml @@ -101,7 +101,7 @@ Dynamic Architecture :id: feat_arc_dyn__persistency__write_key :security: YES :safety: ASIL_B - :fulfils: feat_req__persistency__support_datatype_key,feat_req__persistency__support_datatype_value + :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value :status: valid .. uml:: _assets/kvs_dyn_write_data_key.puml diff --git a/docs/modules/persistency/json/docs/index.rst b/docs/modules/persistency/json/docs/index.rst index d664d2b17c..0b0115f57a 100644 --- a/docs/modules/persistency/json/docs/index.rst +++ b/docs/modules/persistency/json/docs/index.rst @@ -20,7 +20,7 @@ Tiny JSON .. note:: Document header .. document:: Persistency JSON - :id: doc__PersistencyJson + :id: doc__persistencyjson :status: draft :safety: ASIL_B :realizes: wp__cmpt_request diff --git a/docs/modules/persistency/kvs/docs/architecture/index.rst b/docs/modules/persistency/kvs/docs/architecture/index.rst index 0dc52ce7fb..fd39688fc3 100644 --- a/docs/modules/persistency/kvs/docs/architecture/index.rst +++ b/docs/modules/persistency/kvs/docs/architecture/index.rst @@ -69,13 +69,13 @@ The components are designed to cover the expectations from the feature architect (i.e. if already exists a definition it should be taken over and enriched). .. comp_arc_sta:: Component Name (Static View) - :id: comp_arc_sta__persistency_kvs__static_view + :id: comp_arc_sta__persistency__static_view :security: YES :safety: ASIL_D :status: invalid - :implements: logic_arc_int__feature_name__interface_name - :fulfils: comp_req__persistency_kvs__some_title - :includes: comp_arc_sta__persistency_kvs__2 + :implements: + :fulfils: + :includes: comp_arc_sta__persistency__2 .. needarch:: :scale: 50 @@ -87,11 +87,11 @@ Dynamic Architecture -------------------- .. comp_arc_dyn:: Dynamic View - :id: comp_arc_dyn__persistency_kvs__dynamic_view + :id: comp_arc_dyn__persistency__dynamic_view :security: YES :safety: ASIL_D :status: invalid - :fulfils: comp_req__persistency_kvs__some_title + :fulfils: put here a sequence diagram @@ -112,11 +112,11 @@ Lower Level Components ---------------------- .. comp_arc_sta:: Component Name 2 - :id: comp_arc_sta__persistency_kvs__2 + :id: comp_arc_sta__persistency__2 :status: invalid :safety: ASIL_D :security: YES - :implements: logic_arc_int__feature_name__interface_name + :implements: no architecture but detailed design diff --git a/docs/modules/persistency/kvs/docs/index.rst b/docs/modules/persistency/kvs/docs/index.rst index 6654c1f042..c79023fdd1 100644 --- a/docs/modules/persistency/kvs/docs/index.rst +++ b/docs/modules/persistency/kvs/docs/index.rst @@ -20,7 +20,7 @@ KVS (Key Value Store) .. note:: Document header .. document:: Persistency KVS - :id: doc__PersistencyKvs + :id: doc__persistencykvs :status: draft :safety: ASIL_B :realizes: wp__cmpt_request diff --git a/docs/modules/persistency/kvs/docs/requirements/index.rst b/docs/modules/persistency/kvs/docs/requirements/index.rst index 58ee48a028..3c7caf8e7a 100644 --- a/docs/modules/persistency/kvs/docs/requirements/index.rst +++ b/docs/modules/persistency/kvs/docs/requirements/index.rst @@ -47,7 +47,7 @@ Component Requirements :reqtype: Functional :security: NO :safety: QM - :satisfies: feat_req__persistency__default_values,feat_req__persistency__default_value_retrieval,feat_req__persistency__default_value_reset,feat_req__persistency__default_value_file + :satisfies: feat_req__persistency__default_values,feat_req__persistency__default_value_get,feat_req__persistency__default_value_reset,feat_req__persistency__default_value_file :status: valid The component shall accept default values of only permitted value data types. @@ -70,7 +70,7 @@ Component Requirements :reqtype: Functional :security: NO :safety: QM - :satisfies: feat_req__persistency__cpp_rust_interoperability + :satisfies: feat_req__persistency__cpp_rust_interop :status: valid The component shall provide an API that supports bindings to other languages or shall use a storage and memory exchange format that is adaptable to other languages. From 1cb6e1c86105033635c697ad29b3b2840bed4576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20H=C3=A4ussler?= <volker.haeussler@qorix.ai> Date: Wed, 4 Jun 2025 11:13:13 +0200 Subject: [PATCH 034/102] process: fix build errors --- docs/features/persistency/safety_planning/index.rst | 8 ++++---- .../docs/verification/module_verification_report.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/features/persistency/safety_planning/index.rst b/docs/features/persistency/safety_planning/index.rst index c45fd37406..c8864e50d8 100644 --- a/docs/features/persistency/safety_planning/index.rst +++ b/docs/features/persistency/safety_planning/index.rst @@ -31,8 +31,8 @@ Feature Safety Planning - :need:`gd_temp__change__feature_request` - :ndf:`copy('status', need_id='gd_temp__change__feature_request')` - https://github.com/eclipse-score/score/issues/760 - - :need:`doc__feature_name` - - :ndf:`copy('status', need_id='doc__feature_name')` + - :need:`doc__persistency_kvs` + - :ndf:`copy('status', need_id='doc__persistency_kvs')` * - :need:`wp__requirements__feat` - :need:`gd_temp__req__feat_req` @@ -59,14 +59,14 @@ Feature Safety Planning - <link to process> - <automated> - https://github.com/eclipse-score/score/issues/965 - - :doc:`../safety_analysis/doc__persistency_safety_analysis` + - :need:`doc__persistency_safety_analysis` - <automated> * - :need:`wp__feature_dfa` - <Link to process> - <Process status> - https://github.com/eclipse-score/score/issues/965 - - :doc:`../safety_analysis/doc__persistency_dfa` + - :need:`doc__persistency_dfa` - <automated> * - :need:`wp__requirements__inspect` diff --git a/docs/modules/persistency/docs/verification/module_verification_report.rst b/docs/modules/persistency/docs/verification/module_verification_report.rst index 5e4169687b..8af04d22e6 100644 --- a/docs/modules/persistency/docs/verification/module_verification_report.rst +++ b/docs/modules/persistency/docs/verification/module_verification_report.rst @@ -33,7 +33,7 @@ Verification Report - Adjust ``safety`` and ``tags`` according to your needs -This verification report is based on the :need:`SCORE_doc__verification_plan`. +This verification report is based on the verfication plan. It covers all the components of the above stated module. Verification Report contains: From 8755a48a0f0bd9ca69bfaacbd271ff86499bb6c0 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 4 Jun 2025 14:20:49 +0200 Subject: [PATCH 035/102] persistency_kvs: set feature status to valid Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- docs/features/persistency/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index 6111a0fa9d..c1fd244824 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -17,7 +17,7 @@ Key-Value-Storage .. document:: Persistency Key-Value-Storage :id: doc__persistency_kvs - :status: draft + :status: valid :safety: ASIL_B :tags: feature_request, persistency_kvs From becd0c45f13f73923a386ce9ca48b40b4bde0a34 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Thu, 5 Jun 2025 08:45:01 +0200 Subject: [PATCH 036/102] persistency_kvs: adapt needs-links to externalized process docs Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../persistency/safety_planning/index.rst | 50 +++++++++---------- docs/modules/persistency/json/docs/index.rst | 4 +- .../kvs/docs/architecture/index.rst | 2 +- docs/modules/persistency/kvs/docs/index.rst | 4 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/features/persistency/safety_planning/index.rst b/docs/features/persistency/safety_planning/index.rst index c8864e50d8..cd9e60b781 100644 --- a/docs/features/persistency/safety_planning/index.rst +++ b/docs/features/persistency/safety_planning/index.rst @@ -27,65 +27,65 @@ Feature Safety Planning - Link to WP - WP status - * - :need:`wp__feat_request` - - :need:`gd_temp__change__feature_request` - - :ndf:`copy('status', need_id='gd_temp__change__feature_request')` + * - :need:`PROCESS_wp__feat_request` + - :need:`PROCESS_gd_temp__change__feature_request` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__change__feature_request')` - https://github.com/eclipse-score/score/issues/760 - :need:`doc__persistency_kvs` - :ndf:`copy('status', need_id='doc__persistency_kvs')` - * - :need:`wp__requirements__feat` - - :need:`gd_temp__req__feat_req` - - :ndf:`copy('status', need_id='gd_temp__req__feat_req')` + * - :need:`PROCESS_wp__requirements__feat` + - :need:`PROCESS_gd_temp__req__feat_req` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__req__feat_req')` - https://github.com/eclipse-score/score/issues/960 - :doc:`../requirements/index` - see below - * - :need:`wp__requirements__feat_aou` - - :need:`gd_temp__req__aou_req` - - :ndf:`copy('status', need_id='gd_temp__req__aou_req')` + * - :need:`PROCESS_wp__requirements__feat_aou` + - :need:`PROCESS_gd_temp__req__aou_req` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__req__aou_req')` - https://github.com/eclipse-score/score/issues/960 - :doc:`../requirements/index` - see below - * - :need:`wp__feature_arch` - - :need:`gd_temp__arch__feature` - - :ndf:`copy('status', need_id='gd_temp__arch__feature')` + * - :need:`PROCESS_wp__feature_arch` + - :need:`PROCESS_gd_temp__arch__feature` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__arch__feature')` - https://github.com/eclipse-score/score/issues/1020 - :doc:`../architecture/index` - see below - * - :need:`wp__feature_safety_analysis` + * - :need:`PROCESS_wp__feature_safety_analysis` - <link to process> - <automated> - https://github.com/eclipse-score/score/issues/965 - :need:`doc__persistency_safety_analysis` - <automated> - * - :need:`wp__feature_dfa` + * - :need:`PROCESS_wp__feature_dfa` - <Link to process> - <Process status> - https://github.com/eclipse-score/score/issues/965 - :need:`doc__persistency_dfa` - <automated> - * - :need:`wp__requirements__inspect` - - :need:`gd_chklst__req__inspection` - - :ndf:`copy('status', need_id='gd_chklst__req__inspection')` + * - :need:`PROCESS_wp__requirements__inspect` + - :need:`PROCESS_gd_chklst__req__inspection` + - :ndf:`copy('status', need_id='PROCESS_gd_chklst__req__inspection')` - n/a - Checklist used in Pull Request Review - n/a - * - :need:`wp__sw_arch_verification` - - :need:`gd_chklst__arch__inspection_checklist` - - :ndf:`copy('status', need_id='gd_chklst__arch__inspection_checklist')` + * - :need:`PROCESS_wp__sw_arch_verification` + - :need:`PROCESS_gd_chklst__arch__inspection_checklist` + - :ndf:`copy('status', need_id='PROCESS_gd_chklst__arch__inspection_checklist')` - n/a - Checklist used in Pull Request Review - n/a - * - :need:`wp__verification__feat_int_test` - - :need:`gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='gd_guidl__verification_guide')` + * - :need:`PROCESS_wp__verification__feat_int_test` + - :need:`PROCESS_gd_guidl__verification_guide` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` - <link to issue> - https://github.com/eclipse-score/score/issues/964 - <automated> @@ -93,8 +93,8 @@ Feature Safety Planning .. attention:: The above table must be updated according to your feature safety planning. - - Create and link the issues to plan the work products (according to :need:`gd_guidl__saf_plan_definitions`) - - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`gd_guidl__saf_package`) + - Create and link the issues to plan the work products (according to :need:`PROCESS_gd_guidl__saf_plan_definitions`) + - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`PROCESS_gd_guidl__saf_package`) Feature Requirements Status --------------------------- diff --git a/docs/modules/persistency/json/docs/index.rst b/docs/modules/persistency/json/docs/index.rst index 0b0115f57a..e9e1403dcc 100644 --- a/docs/modules/persistency/json/docs/index.rst +++ b/docs/modules/persistency/json/docs/index.rst @@ -71,7 +71,7 @@ Specification .. note:: A CR shall specify the component requirements as part of our platform/project. - Thereby the :need:`rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). + Thereby the :need:`PROCESS_rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). @@ -122,7 +122,7 @@ For new feature/component contributions: [What is the expected classification of the contribution?] .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`gd_temp__component_classification`. + Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`PROCESS_gd_temp__component_classification`. License Impact ============== diff --git a/docs/modules/persistency/kvs/docs/architecture/index.rst b/docs/modules/persistency/kvs/docs/architecture/index.rst index fd39688fc3..a7c0ba8243 100644 --- a/docs/modules/persistency/kvs/docs/architecture/index.rst +++ b/docs/modules/persistency/kvs/docs/architecture/index.rst @@ -126,5 +126,5 @@ Lower Level Components .. attention:: The above directives must be updated according to your component architecture. - - Replace the example content by the real content (according to :need:`gd_guidl__arch__design`) + - Replace the example content by the real content (according to :need:`PROCESS_gd_guidl__arch__design`) - Set the status to valid and start the review/merge process diff --git a/docs/modules/persistency/kvs/docs/index.rst b/docs/modules/persistency/kvs/docs/index.rst index c79023fdd1..5cc5ee50fd 100644 --- a/docs/modules/persistency/kvs/docs/index.rst +++ b/docs/modules/persistency/kvs/docs/index.rst @@ -71,7 +71,7 @@ Specification .. note:: A CR shall specify the component requirements as part of our platform/project. - Thereby the :need:`rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). + Thereby the :need:`PROCESS_rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). @@ -122,7 +122,7 @@ For new feature/component contributions: [What is the expected classification of the contribution?] .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`gd_temp__component_classification`. + Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`PROCESS_gd_temp__component_classification`. License Impact ============== From 701928d0325d6795b89e106dfd017fdafe7448a8 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Thu, 5 Jun 2025 08:49:42 +0200 Subject: [PATCH 037/102] persistency_kvs: removed feat arch & comp reqs for a clean PR Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../architecture/_assets/kvs_dyn_builder.puml | 25 - .../_assets/kvs_dyn_check_value_default.puml | 24 - .../_assets/kvs_dyn_delete_data_key.puml | 16 - .../kvs_dyn_flush_local_repr_to_file.puml | 56 -- .../_assets/kvs_dyn_read_data_key.puml | 20 - .../kvs_dyn_read_file_into_local_repr.puml | 47 - .../_assets/kvs_dyn_restore_snapshot.puml | 16 - .../_assets/kvs_dyn_write_data_key.puml | 11 - .../architecture/_assets/kvs_interface.puml | 21 - .../architecture/_assets/kvs_static_view.puml | 34 - .../persistency/architecture/index.rst | 129 --- docs/features/persistency/index.rst | 4 - .../persistency/safety_analysis/dfa.rst | 868 ------------------ .../persistency/safety_analysis/fmea.rst | 393 -------- .../persistency/safety_planning/index.rst | 130 --- docs/modules/index.rst | 3 - docs/modules/persistency/docs/index.rst | 25 - .../modules/persistency/docs/manual/index.rst | 21 - .../persistency/docs/manual/safety_manual.rst | 89 -- .../persistency/docs/release/release_note.rst | 90 -- .../persistency/docs/safety_mgt/index.rst | 19 - .../module_verification_report.rst | 90 -- .../json/docs/component_classification.rst | 181 ---- docs/modules/persistency/json/docs/index.rst | 176 ---- .../kvs/docs/architecture/index.rst | 130 --- .../kvs/docs/component_classification.rst | 195 ---- docs/modules/persistency/kvs/docs/index.rst | 180 ---- .../kvs/docs/requirements/index.rst | 175 ---- .../kvs/docs/safety_analysis/dfa.rst | 53 -- .../kvs/docs/safety_analysis/fmea.rst | 53 -- 30 files changed, 3274 deletions(-) delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_interface.puml delete mode 100644 docs/features/persistency/architecture/_assets/kvs_static_view.puml delete mode 100644 docs/features/persistency/architecture/index.rst delete mode 100644 docs/features/persistency/safety_analysis/dfa.rst delete mode 100644 docs/features/persistency/safety_analysis/fmea.rst delete mode 100644 docs/features/persistency/safety_planning/index.rst delete mode 100644 docs/modules/persistency/docs/index.rst delete mode 100644 docs/modules/persistency/docs/manual/index.rst delete mode 100644 docs/modules/persistency/docs/manual/safety_manual.rst delete mode 100644 docs/modules/persistency/docs/release/release_note.rst delete mode 100644 docs/modules/persistency/docs/safety_mgt/index.rst delete mode 100644 docs/modules/persistency/docs/verification/module_verification_report.rst delete mode 100644 docs/modules/persistency/json/docs/component_classification.rst delete mode 100644 docs/modules/persistency/json/docs/index.rst delete mode 100644 docs/modules/persistency/kvs/docs/architecture/index.rst delete mode 100644 docs/modules/persistency/kvs/docs/component_classification.rst delete mode 100644 docs/modules/persistency/kvs/docs/index.rst delete mode 100644 docs/modules/persistency/kvs/docs/requirements/index.rst delete mode 100644 docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst delete mode 100644 docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml deleted file mode 100644 index a1b25fe473..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_builder.puml +++ /dev/null @@ -1,25 +0,0 @@ -@startuml - -title Sequence Diagram: Build KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Create KVS builder -kvs --> actor: KVS builder instance - -actor -> kvs: Set need_defaults flag -kvs --> actor: KVS builder instance - -actor -> kvs: Set need_kvs flag -kvs --> actor: KVS builder instance - -actor -> kvs: Build KVS instance - -alt kvs-builder-success - kvs --> actor: KVS instance with builder config -else kvs-builder-error - kvs --> actor: KVS ErrorCode -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml deleted file mode 100644 index 01baa2727f..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_check_value_default.puml +++ /dev/null @@ -1,24 +0,0 @@ -@startuml - -title Sequence Diagram: Check if Key contains Default Value - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Does key have default value - -alt default-key-exists - alt key-exists - alt default-and-key-match - kvs --> actor: Key contains default value - else key-doesnt-exist - kvs --> actor: Key doesn't containt default value - end - else key-doesnt-exist - kvs --> actor: Key contains default value - end -else default-doesnt-exist - kvs --> actor: Key doesn't contain default value -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml deleted file mode 100644 index e2b222e311..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_delete_data_key.puml +++ /dev/null @@ -1,16 +0,0 @@ -@startuml - -title Sequence Diagram: Delete Key from KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Remove key - -alt key-exists - kvs --> actor: Successfully deleted key -else key-doesnt-exist - kvs --> actor: Key-Not-Found-Error -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml deleted file mode 100644 index 947cf782eb..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml +++ /dev/null @@ -1,56 +0,0 @@ -@startuml - -title Sequence Diagram: Flush Local Representation to Data File - -participant "User" as actor -participant "«component» :kvs" as kvs -participant "«component» :json" as json_parser -participant "«component» :fs" as fs - -actor -> kvs: Flush KVS - -kvs -> json_parser: Generate string from local representation - -alt json-string - json_parser --> kvs: JSON data string -else json-string-error - json_parser --> kvs: JSON generator error - kvs --> actor: JSON generator error -end - -kvs -> kvs: Rotate snapshots - -alt snapshot-rotate-success - kvs --> kvs: Snapshots rotated -else snapshot-rotate-error - kvs --> actor: Snapshot-Rotate-Error -end - -kvs -> kvs: Create JSON data hash - -alt hash-created-success - kvs -> kvs: Data hash -else hash-create-error - kvs --> actor: Hash-Calc-Error -end - -kvs -> fs: Write JSON data string to file - -alt file-write - fs --> kvs: File successfully written -else file-write-error - fs --> kvs: File-Write-Error - kvs --> actor: File-Write-Error -end - -kvs -> fs: Write JSON data hash to file - -alt file-hash-write - fs --> kvs: Hash file successfully written - kvs --> actor: Flush successful -else file-hash-write-error - fs --> kvs: File-Hash-Write-Error - kvs --> actor: File-Hash-Write-Error -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml deleted file mode 100644 index 064e248911..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_read_data_key.puml +++ /dev/null @@ -1,20 +0,0 @@ -@startuml - -title Sequence Diagram: Read Key from KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Get value for key - -alt key-exists - kvs --> actor: Return value for key -else key-doesnt-exist - alt default-exists - kvs --> actor: Return default value for key - else default-doesnt-exist - kvs --> actor: Key-Not-Found error - end -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml deleted file mode 100644 index 4a154d24df..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml +++ /dev/null @@ -1,47 +0,0 @@ -@startuml - -title Sequence Diagram: Read Data into Local Representation (KvsValue) - -participant "User" as actor -participant "«component» :kvs" as kvs -participant "«component» :json" as json_parser -participant "«component» :fs" as fs - -actor -> kvs: Open KVS - -kvs -> fs: Read defaults file - -alt file-exists - fs --> kvs: Defaults file content (JSON) -else file-based-error - fs --> kvs: File-Error - kvs -> actor: File-Error -end - -kvs -> fs: Read defaults file hash - -alt file-exists - fs --> kvs: Defaults file hash -else file-based-error - fs --> kvs: File-Error - kvs -> actor: File-Error -end - -kvs -> kvs: Generate defaults file hash - -alt hash-match-success - kvs -> json_parser: Parse JSON data -else hash-match-error - kvs -> actor: Hash-Error -end - -alt parsing-success - json_parser --> kvs: Parsed JSON object -else parsing-based-error - json_parser -> kvs: Parser-Error - kvs -> actor: Parser-Error -end - -kvs --> actor: KVS instance - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml deleted file mode 100644 index 17eb75b382..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_restore_snapshot.puml +++ /dev/null @@ -1,16 +0,0 @@ -@startuml - -title Sequence Diagram: Restore Snapshot - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Restore snapshot - -alt snapshot-restore-success - kvs --> actor: Snapshot restored successfully -else snapshot-restore-error - kvs --> actor: Snapshot-Not-Available-Error -end - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml deleted file mode 100644 index b34c24cc20..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_dyn_write_data_key.puml +++ /dev/null @@ -1,11 +0,0 @@ -@startuml - -title Sequence Diagram: Write Key to KVS Instance - -participant "User" as actor -participant "«component» :kvs" as kvs - -actor -> kvs: Set value for key -kvs --> actor: Value set for key - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_interface.puml b/docs/features/persistency/architecture/_assets/kvs_interface.puml deleted file mode 100644 index 46f65a27cc..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_interface.puml +++ /dev/null @@ -1,21 +0,0 @@ -@startuml - -interface IKvs { - open - flush_on_exit - reset - get_all_keys - key_exists - get_value - get_default_value - has_default_value - set_default_value - set_value - remove_key - flush - snapshot_count - snapshot_max_count - snapshot_restore -} - -@enduml diff --git a/docs/features/persistency/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/architecture/_assets/kvs_static_view.puml deleted file mode 100644 index ebb646f285..0000000000 --- a/docs/features/persistency/architecture/_assets/kvs_static_view.puml +++ /dev/null @@ -1,34 +0,0 @@ -@startuml -allowmixing - -title Static View - kvs - -!include kvs_interface.puml - - -skinparam package { - BackgroundColor #E0E0D0 - BorderColor Black - backgroundColor<<module>> lightgreen -} - -skinparam component { - backgroundColor<<component>> white -} - -' Define Features -package "persistency" <<module>> { - component kvs <<component>> - component fs <<component>> - component json <<component>> -} - - - -kvs --> IKvs : implements - -kvs ..> json : use -kvs ..> fs : use - - -@enduml diff --git a/docs/features/persistency/architecture/index.rst b/docs/features/persistency/architecture/index.rst deleted file mode 100644 index 21ee05d945..0000000000 --- a/docs/features/persistency/architecture/index.rst +++ /dev/null @@ -1,129 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Feature Architecture : persistency/kvs -====================================== - -Overview --------- - -- kvs provides the capability to efficiently store, retrieve, and - manage key-value pairs in a persistent storage system. - -Description ------------ - -- kvs organize data as pairs, where each unique key is associated with a specific value. - The key acts as a unique identifier for getting the value. -- The data is persisted in JSON format to the file system, providing a human-readable, - and widely supported way to store and manage key-value pairs. -- The JSON data persisted is according to RFC-8259. - -Rationale Behind Architecture Decomposition -******************************************* - -- The architecture is decomposed to include a dedicated JSON parser component (json) to facilitate the persistent storage of data in JSON format. -- The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. - - -Static Architecture -------------------- - -.. feat_arc_sta:: Static Architecture - :id: feat_arc_sta__persistency__static - :security: YES - :safety: ASIL_B - :includes: logic_arc_int__persistency__interface - :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value - :status: valid - - .. uml:: _assets/kvs_static_view.puml - -Dynamic Architecture --------------------- -.. feat_arc_dyn:: Check if key contains default value - :id: feat_arc_dyn__persistency__check_key_default - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__default_values,feat_req__persistency__default_value_get - :status: valid - - .. uml:: _assets/kvs_dyn_check_value_default.puml - -.. feat_arc_dyn:: Delete key from KVS instance - :id: feat_arc_dyn__persistency__delete_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__events - :status: valid - - .. uml:: _assets/kvs_dyn_delete_data_key.puml - -.. feat_arc_dyn:: Flush to permanent storage - :id: feat_arc_dyn__persistency__flush - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__integrity_check,feat_req__persistency__snapshots - :status: valid - - .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml - -.. feat_arc_dyn:: Read key value - :id: feat_arc_dyn__persistency__read_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value,feat_req__persistency__default_values,feat_req__persistency__default_value_get - :status: valid - - .. uml:: _assets/kvs_dyn_read_data_key.puml - -.. feat_arc_dyn:: Read data from permanent storage - :id: feat_arc_dyn__persistency__read_from_storage - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__snapshots - :status: valid - - .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml - -.. feat_arc_dyn:: Write value to key - :id: feat_arc_dyn__persistency__write_key - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value - :status: valid - - .. uml:: _assets/kvs_dyn_write_data_key.puml - -.. feat_arc_dyn:: Restore snapshot - :id: feat_arc_dyn__persistency__snapshot_restore - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__snapshots,feat_req__persistency__persist_data,feat_req__persistency__persistency - :status: valid - - .. uml:: _assets/kvs_dyn_restore_snapshot.puml - - -Logical Interfaces ------------------- - -.. logic_arc_int:: Ikvs - :id: logic_arc_int__persistency__interface - :security: YES - :safety: ASIL_B - :fulfils: feat_req__persistency__stable_api - :status: valid - - .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index c1fd244824..5f7c87169a 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -22,11 +22,7 @@ Key-Value-Storage :tags: feature_request, persistency_kvs .. toctree:: - architecture/index.rst requirements/index.rst - safety_analysis/fmea.rst - safety_analysis/dfa.rst - safety_planning/index.rst Feature flag diff --git a/docs/features/persistency/safety_analysis/dfa.rst b/docs/features/persistency/safety_analysis/dfa.rst deleted file mode 100644 index 8aed7eed32..0000000000 --- a/docs/features/persistency/safety_analysis/dfa.rst +++ /dev/null @@ -1,868 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Persistency DFA -############### - -.. document:: DFA - :id: doc__persistency_dfa - :status: draft - :safety: ASIL_B - :tags: feature_persistency - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_01 - | :violation_cause: Reused software module. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_02 - | :violation_cause: Libraries. . N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_04 - | :violation_cause: Basic software. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_05 - | :violation_cause: Operating system including scheduler. Platformebene. Nicht von Middleware handlebar - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_06 - | :violation_cause: Any service stack, e.g. communication stack. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_07 - | :violation_cause: Configuration data. Return values might be falsified. - | :mitigation: < NONE|ID from Feature Requirement> Integritry check feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_09 - | :violation_cause: Execution time. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SR_01_10 - | :violation_cause: Allocated memory. Diskussion aktuell in Feature-Community. JSON kann das, sollte aber eigentlich nicht erlaubt sein - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_01 - | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) <- Checken ob das Fehlerbild überhaupt passt. 1. Satzteil nicht passen zu 2.> - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_02 - | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information. Fehlerhafte ausführung oder nichtverfügbarkeit vom feature - | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_03 - | :violation_cause: Insertion / sequence of information wie CO_01_02 - | :mitigation: < NONE|ID from Feature Requirement> feat_req__persistency__integrity_check - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_04 - | :violation_cause: Corruption of information, inconsistent data wie CO_01_02 - | :mitigation: < NONE|ID from Feature Requirement> keine Erkennung - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_05 - | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_06 - | :violation_cause: Information from a sender received by only a subset of the receivers. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: CO_01_07 - | :violation_cause: Blocking access to a communication channel N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_02 - | :violation_cause: Configuration data. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_03 - | :violation_cause: Constants, or variables, being global to the two software functions. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_04 - | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SI_01_05 - | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function. Unklar was das Fehlerbild ist - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_01 - | :violation_cause: Memory miss-allocation and leaks. Platformebene - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_02 - | :violation_cause: Read/Write access to memory allocated to another software element. Platformebene - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_03 - | :violation_cause: Stack/Buffer under-/overflow. Könnte passieren, ist aber unwahrscheinlich in RUST. Recursive Funktionen könnten die Ursache sein. - | :mitigation: < NONE|ID from Feature Requirement> Compilerüberwachung / AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_04 - | :violation_cause: Deadlocks. Könnten auftreten. Würde von Applikation verursacht werden. KVS kann da nichts machen - | :mitigation: < NONE|ID from Feature Requirement> AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_05 - | :violation_cause: Livelocks wie UI_01_04 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_06 - | :violation_cause: Blocking of execution. Feature is not available. - | :mitigation: < NONE|ID from Feature Requirement> AoU - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_07 - | :violation_cause: Incorrect allocation of execution time. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_08 - | :violation_cause: Incorrect execution flow N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_09 - | :violation_cause: Incorrect synchronization between software elements N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_10 - | :violation_cause: CPU time depletion N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_11 - | :violation_cause: Memory depletion N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: UI_01_12 - | :violation_cause: Other HW unavailability N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_02 - | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_03 - | :violation_cause: Same personal - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_04 - | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: Persistency - | :verifies: feat_arc_dyn__persistency__check_key_default - | :id: feat_saf_DFA__persistency__check_key_default - | :violation_id: SC_01_05 - | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - - - - - - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_01 - | :violation_cause: Reused software modules - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_02 - | :violation_cause: Libraries - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_04 - | :violation_cause: Basic software - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_05 - | :violation_cause: Operating system including scheduler - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_06 - | :violation_cause: Any service stack, e.g. communication stack - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_07 - | :violation_cause: Configuration data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_09 - | :violation_cause: Execution time - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SR_01_10 - | :violation_cause: Allocated memory - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_01 - | :violation_cause: Information passed via argument through a function call, or via writing/reading a variable being global to the two software functions (data flow) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_02 - | :violation_cause: Data or message corruption / repetition / loss / delay / masquerading or incorrect addressing of information - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_03 - | :violation_cause: Insertion / sequence of information - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_04 - | :violation_cause: Corruption of information, inconsistent data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_05 - | :violation_cause: Asymmetric information sent from a sender to multiple receivers, so that not all defined receivers have the same informations - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_06 - | :violation_cause: Information from a sender received by only a subset of the receivers - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: CO_01_07 - | :violation_cause: Blocking access to a communication channel - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_02 - | :violation_cause: Configuration data - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_03 - | :violation_cause: Constants, or variables, being global to the two software functions - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_04 - | :violation_cause: Basic software passes data (read from hardware register and converted into logical information) to two applications software functions - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SI_01_05 - | :violation_cause: Data / function parameter arguments / messages delivered by software function to more than one other function - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_01 - | :violation_cause: Memory miss-allocation and leaks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_02 - | :violation_cause: Read/Write access to memory allocated to another software element - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_03 - | :violation_cause: Stack/Buffer under-/overflow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_04 - | :violation_cause: Deadlocks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_05 - | :violation_cause: Livelocks - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_06 - | :violation_cause: Blocking of execution - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_07 - | :violation_cause: Incorrect allocation of execution time - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_08 - | :violation_cause: Incorrect execution flow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_09 - | :violation_cause: Incorrect synchronization between software elements - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_10 - | :violation_cause: CPU time depletion - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_11 - | :violation_cause: Memory depletion - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: UI_01_12 - | :violation_cause: Other HW unavailability - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_02 - | :violation_cause: Same development approaches (e.g. IDE, programming and/or modelling language) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_03 - | :violation_cause: Same personal - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_04 - | :violation_cause: Same social-cultural context (even if different personnel). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_dfa:: <Element descriptor> - | :verifies: <Feature architecture> - | :id: feat_saf_DFA__<Feature>__<Element descriptor> - | :violation_id: SC_01_05 - | :violation_cause: Development fault (e.g. human error, insufficient qualification, insufficient methods). Only applicable if diverse development is needed. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> diff --git a/docs/features/persistency/safety_analysis/fmea.rst b/docs/features/persistency/safety_analysis/fmea.rst deleted file mode 100644 index 7097c89ac2..0000000000 --- a/docs/features/persistency/safety_analysis/fmea.rst +++ /dev/null @@ -1,393 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Persistency Safety Analysis -########################### - -.. document:: Safety Analysis - :id: doc__persistency_safety_analysis - :status: draft - :safety: ASIL_B - :tags: feature_persistency - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_01 - | :failure_effect: Message is not received. User is not able to use the feature. Middleware cant be used.A - | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_02 - | :failure_effect: message received too late. User might not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> AoU: Detetion and error handling shall be done outside of the middleware. - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_03 - | :failure_effect: message received too early. No impact / feature reacts only if triggered on the trigger. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_04 - | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost). N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_05 - | :failure_effect: message is corrupted. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_06 - | :failure_effect: message is not sent. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: MF_01_07 - | :failure_effect: message is unintended sent. Covered by MF_01_01 - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: CO_01_01 - | :failure_effect: minimum constraint boundary is violated. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: CO_01_02 - | :failure_effect: maximum constraint boundary is violated. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_01 - | :failure_effect: Process calculates wrong result(s). Feature is not usable. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_02 - | :failure_effect: processing too slow. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_03 - | :failure_effect: processing too fast. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_04 - | :failure_effect: loss of execution. User is not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_05 - | :failure_effect: processing changes to arbitrary process. N/A - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: feat_arc_sta__persistency__static - | :id: feat_saf_FMEA__persistency__open_KVS - | :failure_mode: EX_01_06 - | :failure_effect: processing is not complete (infinite loop). User is not able to use the feature. Middleware cant be used. - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - - - - - - - - - - - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_01 - | :failure_effect: message is not received - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_02 - | :failure_effect: message received too late - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_03 - | :failure_effect: message received too early - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_04 - | :failure_effect: message not received correctly by all recipients (different messages or messages partly lost) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_05 - | :failure_effect: message is corrupted - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_06 - | :failure_effect: message is not sent - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: MF_01_07 - | :failure_effect: message is unintended sent - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: CO_01_01 - | :failure_effect: minimum constraint boundary is violated - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: CO_01_02 - | :failure_effect: maximum constraint boundary is violated - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_01 - | :failure_effect: Process calculates wrong result(s) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_02 - | :failure_effect: processing too slow - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_03 - | :failure_effect: processing too fast - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_04 - | :failure_effect: loss of execution - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_05 - | :failure_effect: processing changes to arbitrary process - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> - - | .. feat_saf_fmea:: Persistency - | :verifies: <Feature architecture> - | :id: feat_saf_FMEA__persistency__<Element descriptor> - | :failure_mode: EX_01_06 - | :failure_effect: processing is not complete (infinite loop) - | :mitigation: < NONE|ID from Feature Requirement> - | :mitigation_issue: <ID from Issue Tracker| None if no issue needed> - | :mitigation_coverage: <0..100%> - | :sufficient: <yes|no> - | :argument: <text to argument why mitigation is sufficient> - | :status: <valid|invalid> diff --git a/docs/features/persistency/safety_planning/index.rst b/docs/features/persistency/safety_planning/index.rst deleted file mode 100644 index cd9e60b781..0000000000 --- a/docs/features/persistency/safety_planning/index.rst +++ /dev/null @@ -1,130 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _feature_safety_wp_template: - -Feature Safety Planning -======================= - -.. list-table:: Feature <feature> Workproducts - :header-rows: 1 - - * - Workproduct Id - - Link to process - - Process status - - Link to issue - - Link to WP - - WP status - - * - :need:`PROCESS_wp__feat_request` - - :need:`PROCESS_gd_temp__change__feature_request` - - :ndf:`copy('status', need_id='PROCESS_gd_temp__change__feature_request')` - - https://github.com/eclipse-score/score/issues/760 - - :need:`doc__persistency_kvs` - - :ndf:`copy('status', need_id='doc__persistency_kvs')` - - * - :need:`PROCESS_wp__requirements__feat` - - :need:`PROCESS_gd_temp__req__feat_req` - - :ndf:`copy('status', need_id='PROCESS_gd_temp__req__feat_req')` - - https://github.com/eclipse-score/score/issues/960 - - :doc:`../requirements/index` - - see below - - * - :need:`PROCESS_wp__requirements__feat_aou` - - :need:`PROCESS_gd_temp__req__aou_req` - - :ndf:`copy('status', need_id='PROCESS_gd_temp__req__aou_req')` - - https://github.com/eclipse-score/score/issues/960 - - :doc:`../requirements/index` - - see below - - * - :need:`PROCESS_wp__feature_arch` - - :need:`PROCESS_gd_temp__arch__feature` - - :ndf:`copy('status', need_id='PROCESS_gd_temp__arch__feature')` - - https://github.com/eclipse-score/score/issues/1020 - - :doc:`../architecture/index` - - see below - - * - :need:`PROCESS_wp__feature_safety_analysis` - - <link to process> - - <automated> - - https://github.com/eclipse-score/score/issues/965 - - :need:`doc__persistency_safety_analysis` - - <automated> - - * - :need:`PROCESS_wp__feature_dfa` - - <Link to process> - - <Process status> - - https://github.com/eclipse-score/score/issues/965 - - :need:`doc__persistency_dfa` - - <automated> - - * - :need:`PROCESS_wp__requirements__inspect` - - :need:`PROCESS_gd_chklst__req__inspection` - - :ndf:`copy('status', need_id='PROCESS_gd_chklst__req__inspection')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`PROCESS_wp__sw_arch_verification` - - :need:`PROCESS_gd_chklst__arch__inspection_checklist` - - :ndf:`copy('status', need_id='PROCESS_gd_chklst__arch__inspection_checklist')` - - n/a - - Checklist used in Pull Request Review - - n/a - - * - :need:`PROCESS_wp__verification__feat_int_test` - - :need:`PROCESS_gd_guidl__verification_guide` - - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` - - <link to issue> - - https://github.com/eclipse-score/score/issues/964 - - <automated> - -.. attention:: - The above table must be updated according to your feature safety planning. - - - Create and link the issues to plan the work products (according to :need:`PROCESS_gd_guidl__saf_plan_definitions`) - - Fill the work producs links and add their status (also possible below) to create the safety package (according to :need:`PROCESS_gd_guidl__saf_package`) - -Feature Requirements Status ---------------------------- - -.. needtable:: - :style: table - :types: feat_req - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title - -Feature AoU Status ------------------- - -.. needtable:: - :style: table - :types: aou_req - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title - -Feature Architecture Status ---------------------------- - -.. needtable:: - :style: table - :types: feat_arc_sta; feat_arc_dyn - :tags: feature_name - :columns: id;status - :colwidths: 25,25 - :sort: title diff --git a/docs/modules/index.rst b/docs/modules/index.rst index 616910914d..6dc626e889 100644 --- a/docs/modules/index.rst +++ b/docs/modules/index.rst @@ -20,6 +20,3 @@ Module .. toctree:: :maxdepth: 1 :glob: - - */docs/index - */*/docs/index diff --git a/docs/modules/persistency/docs/index.rst b/docs/modules/persistency/docs/index.rst deleted file mode 100644 index 3fc9455078..0000000000 --- a/docs/modules/persistency/docs/index.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Module Documents Persistency -############################ - -.. toctree:: - :maxdepth: 1 - :glob: - - manual/index.rst - safety_mgt/index.rst - verification/module_verification_report.rst - release/release_note.rst diff --git a/docs/modules/persistency/docs/manual/index.rst b/docs/modules/persistency/docs/manual/index.rst deleted file mode 100644 index 08ba1a6e1a..0000000000 --- a/docs/modules/persistency/docs/manual/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Manuals -####### - -.. toctree:: - :titlesonly: - - safety_manual diff --git a/docs/modules/persistency/docs/manual/safety_manual.rst b/docs/modules/persistency/docs/manual/safety_manual.rst deleted file mode 100644 index 70108acee3..0000000000 --- a/docs/modules/persistency/docs/manual/safety_manual.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Safety Manual Template -====================== - -.. document:: Persistency Safety Manual - :id: doc__persistency_safety_manual - :status: draft - :safety: ASIL_B - :tags: feature_persistency - -This document implements <add "need" link> - -Introduction/Scope ------------------- -| This manual will cover the Feature Persistency. It's based on the components - -Assumed Platform Safety Requirements ------------------------------------- -| For the <S-CORE platform / module name> the following safety related stakeholder requirements are assumed to define the top level functionality (purpose) of the <S-CORE platform / module name>. I.e. from these all the feature and component requirements implemented are derived. -| <List here all the stakeholder requirements, with safety not equal to QM, the module's components requirements are derived from.> - -Assumptions of Use ------------------- - -Assumptions on the Environment -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -| Generally the assumption of the S-CORE platform SEooC is that it is integrated in a safe system, i.e. the POSIX OS it runs on is qualified and also the HW related failures are taken into account by the system integrator, if not otherwise stated in the module's safety concept. -| <List here all the OS calls the S-CORE platform expects to be safe.> - -List of AoUs expected from the environment the platform / module runs on: - -.. needtable:: - :style: table - :columns: title;id;status - :colwidths: 25,25,25 - :sort: title - - results = [] - - for need in needs.filter_types(["aou_req"]): - if need and "environment" in need["tags"]: - results.append(need) - -Assumptions on the User -^^^^^^^^^^^^^^^^^^^^^^^ -| As there is no assumption on which specific OS and HW is used, the integration testing of the stakeholder and feature requirements is expected to be performed by the user of the platform SEooC. Tests covering all stakeholder and feature requirements performed on a reference platform (tbd link to reference platform specification), reviewed and passed are included in the platform SEooC safety case. -| Additionally the components of the platform may have additional specific assumptions how they are used. These are part of every module documentation: <link to add>. Assumptions from components to their users can be fulfilled in two ways: -| 1. There are assumption which need to be fulfilled by all SW components, e.g. "every user of an IPC mechanism needs to make sure that he provides correct data (including appropriate ASIL level)" - in this case the AoU is marked as "platform". -| 2. There are assumption which can be fulfilled by a safety mechanism realized by some other S-CORE platform component and are therefore not relevant for an user who uses the whole platform. But those are relevant if you chose to use the module SEooC stand-alone - in this case the AoU is marked as "module". An example would be the "JSON read" which requires "The user shall provide a string as input which is not corrupted due to HW or QM SW errors." - which is covered when using together with safe S-CORE platform persistency feature. - -List of AoUs on the user of the platform features or the module of this safety manual: - -.. needtable:: - :style: table - :columns: title;id;status - :colwidths: 25,25,25 - :sort: title - - results = [] - - for need in needs.filter_types(["aou_req"]): - if need and "environment" not in need["tags"]: - results.append(need) - -Safety concept of the SEooC ---------------------------- -| <Describe here the safety concept incl. which faults are taken care of, reactions of the implemented functions under anomalous operating conditions ... if this is not already documented sufficiently in the feature documentation "safety impact" section of all the features the module is used in.> - -Safety Anomalies ----------------- -| Anomalies (bugs in ASIL SW, detected by testing or by users, which could not be fixed) known before release are documented in the platform/module release notes <add link to release note>. - -References ----------- -| <link to the user manual> -| <other links> diff --git a/docs/modules/persistency/docs/release/release_note.rst b/docs/modules/persistency/docs/release/release_note.rst deleted file mode 100644 index 80682eb639..0000000000 --- a/docs/modules/persistency/docs/release/release_note.rst +++ /dev/null @@ -1,90 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Release Note -============ - -.. note:: Document header - -.. document:: [Your Module Name] Release Note - :id: doc__module_name_release_note - :status: draft - :safety: ASIL_D - :realizes: wp__module_sw_release_note - :tags: template - -.. attention:: - The above directive must be updated according to your Module. - - - Modify ``Your Module Name`` to be your Module Name - - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``release_note`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - - - -| Module Name: [Module Name] -| Release Tag: vX.Y.Z -| Release Commit Hash: a1b2c3d4e5f6g7h8i9j0 -| Release Date: YYYY-MM-DD -| -| Overview -| -------- -| -| This document provides an overview of the changes, improvements, and bug fixes included in the software module release version vX.Y.Z. -| -| New Features -| ------------ -| -| - **Feature 1**: Brief description of the new feature. -| - **Feature 2**: Brief description of the new feature. -| - **Feature 3**: Brief description of the new feature. -| -| Improvements -| ------------ -| -| - **Improvement 1**: Brief description of the improvement. -| - **Improvement 2**: Brief description of the improvement. -| - **Improvement 3**: Brief description of the improvement. -| -| Bug Fixes -| --------- -| -| - **Bug 1**: Brief description of the bug fix. -| - **Bug 2**: Brief description of the bug fix. -| - **Bug 3**: Brief description of the bug fix. -| -| Compatibility -| ------------- -| -| - **Dependencies**: List any dependencies and their versions. -| -| Known Issues -| ------------ -| -| - **Issue 1**: Brief description of the known issue. Justification regarding safety impact. -| - **Issue 2**: Brief description of the known issue. Justification regarding safety impact. -| - **Issue 3**: Brief description of the known issue. Justification regarding safety impact. -| -| Upgrade Instructions -| -------------------- -| -| 1. **Step 1**: Description of the first step. -| 2. **Step 2**: Description of the second step. -| 3. **Step 3**: Description of the third step. -| -| Contact Information -| ------------------- -| -| For any questions or support, please contact the *Project lead* or raise an issue/discussion. diff --git a/docs/modules/persistency/docs/safety_mgt/index.rst b/docs/modules/persistency/docs/safety_mgt/index.rst deleted file mode 100644 index fa3a7ff35c..0000000000 --- a/docs/modules/persistency/docs/safety_mgt/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Safety Management -################# - -.. toctree:: - :titlesonly: diff --git a/docs/modules/persistency/docs/verification/module_verification_report.rst b/docs/modules/persistency/docs/verification/module_verification_report.rst deleted file mode 100644 index 8af04d22e6..0000000000 --- a/docs/modules/persistency/docs/verification/module_verification_report.rst +++ /dev/null @@ -1,90 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Verification Report -=================== - -.. note:: Document header - -.. document:: [Your Module Name] Verification Report - :id: doc__module_name_verification_report - :status: draft - :safety: ASIL_D - :realizes: wp__verification__module_ver_report - :tags: template - -.. attention:: - The above directive must be updated according to your Module. - - - Modify ``Your Module Name`` to be your Module Name - - Modify ``id`` to be your Module Name in upper snake case preceded by ``doc_`` and succeeded by ``verification_report`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - - -This verification report is based on the verfication plan. -It covers all the components of the above stated module. - -Verification Report contains: - -**1. Verification Coverage** - -**1.1. on Requirements** - - Lists of component requirements (incl. AoU satisfied by the component) tested by which test case, passed/failed and completeness verdict - (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) - - For external component Assumptions of Use: coverage by platform safety manual or feature/components incl. test case, passed/failed and completeness verdict - - This is split in a list of QM requirements tested and a separate list of tests for ASIL rated requirements. - - List of component requirements (ASIL rated) linked to inspection checklist and verdict (derived from PR export) - -**1.2. on Architecture** - - List of component architecture tags tested by which test case, passed/failed and completeness verdict - (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) - - This is split in a list of QM components tested and a separate list of tests for ASIL rated components. - - List of component architecture tags (ASIL rated) linked to inspection checklist and verdict (derived from PR export) - -**1.3. on Detailed Design** - - List of detailed design tags tested by which test case, passed/failed and completeness verdict - (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) - - This is split in a list of QM components tested and a separate list of tests for ASIL rated components. - - List of detailed design tags (ASIL rated) linked to inspection checklist and verdict (derived from PR export) - - - The lists may also contain other verification methods like "Analysis" - process tbd - -**2. DFA Report** - - List of the performed component DFA, pass/fail with open mitigations - -**3. Safety Analysis Report** - - List of the performed component Safety Analysis, pass/fail with open mitigations - -**4. Unit Verification Coverage** - -**4.1. Structural Coverage** - - List of the units with C0(line) and C1(branch) coverage absolute and percentage - (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) - - List includes a column for the safety rating of each unit. - -**4.2. Static Code Analysis** - - List of the units with compiler warning numbers and coding rule violation numbers - (this shall be generated by tools and accompanied by progress charts to be usable also for project steering) - - List includes a column for the safety rating of each unit. - -**4.3. Manual Code Inspection** - - List of components (ASIL rated) linked to inspection checklist and verdict (derived from PR export) - -**5. Software component qualification verification report** - - Contains the needed verification results if for some components a qualification of pre-developed SW is performed. - -**Note1:** The verification report is valid for the module version tagged together with the report - -**Note2:** All the above lists are generated automatically diff --git a/docs/modules/persistency/json/docs/component_classification.rst b/docs/modules/persistency/json/docs/component_classification.rst deleted file mode 100644 index 68d3a5d262..0000000000 --- a/docs/modules/persistency/json/docs/component_classification.rst +++ /dev/null @@ -1,181 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Component Classification -======================== - -.. document:: Persistency Component Classification - :id: doc__persistency_component_classification - :status: draft - :safety: ASIL_B - :realizes: wp__sw_component_class - :tags: feature_persistency - -| Classification of tiny json -| -| `tiny jason <https://github.com/rhysd/tinyjson>`_ V.2.5.1 -| -| Additional documentation considered: -| `Documentation for tiny jason <https://docs.rs/tinyjson/latest/tinyjson/>`_ - - -Step 1: Determine (P): the uncertainty of the Processes applied ---------------------------------------------------------------- - -| Apply the process measures to determine (P). -| The result of a process measure shall have as outcome [HE, PE, NE] -| - HE: High Evidence -| - PE: Partly Evidence but Manageable -| - NE: No Evidence - -.. list-table:: Determine (P) - :header-rows: 1 - - * - Id - - Indicator for applying process - - Result - - Rationale for result - - * - 1 - - Are rules, state-of-the art processes applied for the design, implementation and verification? - - PE - - Rules for Safe Rust applied. - - * - 2 - - Are requirements available? - - PE - - n/a. Tinyjson is a library to parse/generate JSON format document. So this is the main requirement. - - * - 3 - - Are specifications for functionalities and properties available (architecture)? - - PE - - Yes in the documentation of tinyjson. - - * - 4 - - Are design specifications available? - - PE - - n/a - - * - 5 - - Are configuration specification and data available, if applicable? - - PE - - Yes in the documentation of tinyjson. - - * - 6 - - Are verification measures including tests and reports available? - - HE - - Stored in github repo within folder tests. - - -| (P=1) shall be selected when none of the determined process measures indicate PE or NE. -| (P=2) shall be selected when at least one of the determined process measures indicate PE or NE, but the gaps evaluated are acceptable, means -| the risk of systematic faults due to these gaps is sufficiently low or manageable by mitigating the gaps. -| (P=3) in all other cases. - -Tinyjson determined as P=2. - - -Step 2: Determine (C): the uncertainty of finding systematic faults based on the Complexity -------------------------------------------------------------------------------------------- - -| Apply the complexity measures to determine (C). -| The result of a complexity measure shall have as outcome [NH, HM, NM] -| - NH: Not High -| - HM: High but Manageable -| - NM: high and Not Manageable -| -| **Complexity measure for programming language: <C++ or RUST>** - -.. list-table:: Determine (C) for RUST - :header-rows: 1 - - * - Id - - Indicator for high Complexity - - Complexity measure Tool - - Result - - Number - - * - 1 - - High amount of Lines of Code - - Lines of Code (without comments) (generated code is excluded, e.g. ProtoCmpl) - - NH - - 2367 loc - - * - 2 - - Unsafe code used / total unsafe code - - Count: - * LoUC+N: lines of unsafe code with safety note - * LoUC : lines of unsafe code, no safety note - - NH. Tinyjson is written in Safe Rust. - - 0 - - * - 3 - - | Test exists / Coverage (Function, Line) - | (maybe better: testability, but how to measure?) - - Existing Tests Coverage - - NH - - <Number> - - * - 4 - - High amount of public function interfaces - - Number of public function interfaces - - NH - - <Number> - - * - 5 - - High amount of function parameters - - Number of parameters - - NH - - <Number> - - -| (C=1) shall be selected when none of the determined complexity measures indicate HM or NM. -| (C=2) shall be selected when at least one of the determined complexity measures indicate HM or NM, but the gaps evaluated are acceptable, means -| the risk of systematic faults due to these gaps is sufficiently low in the context of S-CORE or manageable by mitigating the gaps. -| (C=3) in all other cases. -| - -Tinyjson is determined as C=1 - - -Step 3: Determine (CLAS_OUT): the classification outcome --------------------------------------------------------- - -| Select CLAS_OUT depending on the determined values of (C) and (P) - -+-------+-----------------------+ -| ( C ) | ( P ) | -+-------+-------+-------+-------+ -| | 1 | 2 | 3 | -+=======+=======+=======+=======+ -| 1 | Q | Q | QR | -+-------+-------+-------+-------+ -| 2 | QR | QR | QR | -+-------+-------+-------+-------+ -| 3 | QR | QR | NQ | -+-------+-------+-------+-------+ - -Tinyjson is classified as CLAS_OUT=Q - - -Step 4: Document all results and rationale for choosing (P) and (C) and (CLAS_OUT) ----------------------------------------------------------------------------------- -This document - - -Step 5: Based on (CLAS_OUT) select the activities -------------------------------------------------- - -| As soon as the contribution request containing this is in status "Accepted", the module safety plan for the component development is adapted based on the following: -| - Q: Follow the processes for qualification of software components in a safety context. diff --git a/docs/modules/persistency/json/docs/index.rst b/docs/modules/persistency/json/docs/index.rst deleted file mode 100644 index e9e1403dcc..0000000000 --- a/docs/modules/persistency/json/docs/index.rst +++ /dev/null @@ -1,176 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _component_PersistencyJson: - -Tiny JSON -######### - -.. note:: Document header - -.. document:: Persistency JSON - :id: doc__persistencyjson - :status: draft - :safety: ASIL_B - :realizes: wp__cmpt_request - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``document`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Abstract -======== - -[A short (~200 word) description of the contribution being addressed.] - - -Motivation -========== - -[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] - - .. note:: - The motivation is critical for CRs that want to change the existing components. - It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. - Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. - CRs submissions without sufficient motivation may be rejected. - - - -Rationale -========= - -[Describe why particular design decisions were made.] - - - .. note:: - The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. - - -Specification -============= - -[Describe the requirements, architecture of any new component.] or -[Describe the change to requirements, architecture, implementation, documentation of any change request.] - - .. note:: - A CR shall specify the component requirements as part of our platform/project. - Thereby the :need:`PROCESS_rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). - - - -Backwards Compatibility -======================= - -[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] - - -Security Impact -=============== - -[How could a malicious user take advantage of this new/modified component?] - - .. note:: - If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which security requirements are affected or has to be changed? -Could the new/modified component enable new threat scenarios? -Could the new/modified component enable new attack paths? -Could the new/modified component impact functional safety? -If applicable, which additional security measures must be implemented to mitigate the risk? - - .. note:: - Use Security Software Critically Analysis, Vulnerability Analysis. - [Methods will be defined later in Process area Security Analysis] - - -Safety Impact -============= - -[How could the safety be impacted by the new/modified component?] - - .. note:: - If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which safety requirements are affected or has to be changed? -Could the new/modified component be a potential common cause or cascading failure initiator? -If applicable, which additional safety measures must be implemented to mitigate the risk? - - .. note:: - Use Dependency Failure Analysis and/or Safety Software Critically Analysis. - [Methods will be defined later in Process area Safety Analysis] - -For new feature/component contributions: - -[What is the expected ASIL level?] -[What is the expected classification of the contribution?] - - .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`PROCESS_gd_temp__component_classification`. - -License Impact -============== - -[How could the copyright impacted by the license of the new contribution?] - - -How to Teach This -================= - -[How to teach users, new and experienced, how to apply the CR to their work.] - - .. note:: - For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. - - - -Rejected Ideas -============== - -[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] - - .. note:: - Throughout the discussion of a CR, various ideas will be proposed which are not accepted. - Those rejected ideas should be recorded along with the reasoning as to why they were rejected. - This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. - In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. - - - -Open Issues -=========== - -[Any points that are still being decided/discussed.] - - .. note:: - While a CR is in draft, ideas can come up which warrant further discussion. - Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. - This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. - - - -Footnotes -========= - -[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] - -.. toctree:: - :hidden: - - component_classification.rst diff --git a/docs/modules/persistency/kvs/docs/architecture/index.rst b/docs/modules/persistency/kvs/docs/architecture/index.rst deleted file mode 100644 index a7c0ba8243..0000000000 --- a/docs/modules/persistency/kvs/docs/architecture/index.rst +++ /dev/null @@ -1,130 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _component_architecture_PersistencyKvs: - -Component Architecture -====================== - -.. document:: Persistency KVS Architecture - :id: doc__persistency_kvs_architecture - :status: draft - :safety: ASIL_B - :realizes: wp__component_arch - :tags: template - -.. attention:: - The above directive must be updated according to your needs. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and followed by ``_architecture`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Overview --------- -Brief summary - -Requirements Linked to Component Architecture ---------------------------------------------- - -.. code-block:: none - - .. needtable:: Overview of Component Requirements - :style: table - :columns: title;id - :filter: search("comp_arch_sta__archdes$", "fulfils_back") - :colwidths: 70,30 - -Description ------------ - -General Description - -Design Decisions - -Design Constraints - -Rationale Behind Architecture Decomposition -******************************************* -mandatory: a motivation for the decomposition or reason for not further splitting it into sub components. - -.. note:: Common decisions across components / cross cutting concepts is at the higher level. - -Static Architecture -------------------- - -The components are designed to cover the expectations from the feature architecture -(i.e. if already exists a definition it should be taken over and enriched). - -.. comp_arc_sta:: Component Name (Static View) - :id: comp_arc_sta__persistency__static_view - :security: YES - :safety: ASIL_D - :status: invalid - :implements: - :fulfils: - :includes: comp_arc_sta__persistency__2 - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_component(need(), needs) }} - -Dynamic Architecture --------------------- - -.. comp_arc_dyn:: Dynamic View - :id: comp_arc_dyn__persistency__dynamic_view - :security: YES - :safety: ASIL_D - :status: invalid - :fulfils: - - put here a sequence diagram - - -Interfaces ----------- - -.. code-block:: rst - - .. real_arc_int:: <Title> - :id: real_arc_int__<component>__<Title> - :security: <YES|NO> - :safety: <QM|ASIL_B|ASIL_D> - :fulfils: <link to component requirement id> - :language: cpp - -Lower Level Components ----------------------- - -.. comp_arc_sta:: Component Name 2 - :id: comp_arc_sta__persistency__2 - :status: invalid - :safety: ASIL_D - :security: YES - :implements: - - no architecture but detailed design - -.. note:: - Architecture can be split into multiple files. At component level the public interfaces to be used by the user and tester to be shown. - -.. attention:: - The above directives must be updated according to your component architecture. - - - Replace the example content by the real content (according to :need:`PROCESS_gd_guidl__arch__design`) - - Set the status to valid and start the review/merge process diff --git a/docs/modules/persistency/kvs/docs/component_classification.rst b/docs/modules/persistency/kvs/docs/component_classification.rst deleted file mode 100644 index 7a6214f3a3..0000000000 --- a/docs/modules/persistency/kvs/docs/component_classification.rst +++ /dev/null @@ -1,195 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Component Classification -======================== - -.. note:: Document header - -.. document:: [Your Component Name] Component Classification - :id: doc__component_name_comp_class - :status: draft - :safety: ASIL_D - :realizes: wp__sw_component_class - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -| Classification of <component> -| -| <Link to OSS component source (e.g. in github) including the selected version> -| -| Additional documentation considered: -| <list of documentation links> - - -Step 1: Determine (P): the uncertainty of the Processes applied ---------------------------------------------------------------- - -| Apply the process measures to determine (P). -| The result of a process measure shall have as outcome [HE, PE, NE] -| - HE: High Evidence -| - PE: Partly Evidence but Manageable -| - NE: No Evidence - -.. list-table:: Determine (P) - :header-rows: 1 - - * - Id - - Indicator for applying process - - Result - - Rationale for result - - * - 1 - - Are rules, state-of-the art processes applied for the design, implementation and verification? - - <HE|PE|NE> - - <Rationale for result> - - * - 2 - - Are requirements available? - - <HE|PE|NE> - - <Rationale for result> - - * - 3 - - Are specifications for functionalities and properties available (architecture)? - - <HE|PE|NE> - - <Rationale for result> - - * - 4 - - Are design specifications available? - - <HE|PE|NE> - - <Rationale for result> - - * - 5 - - Are configuration specification and data available, if applicable? - - <HE|PE|NE> - - <Rationale for result> - - * - 6 - - Are verification measures including tests and reports available? - - <HE|PE|NE> - - <Rationale for result> - - -| (P=1) shall be selected when none of the determined process measures indicate PE or NE. -| (P=2) shall be selected when at least one of the determined process measures indicate PE or NE, but the gaps evaluated are acceptable, means -| the risk of systematic faults due to these gaps is sufficiently low or manageable by mitigating the gaps. -| (P=3) in all other cases. - -<component name> is determined as P=<1|2|3> - - -Step 2: Determine (C): the uncertainty of finding systematic faults based on the Complexity -------------------------------------------------------------------------------------------- - -| Apply the complexity measures to determine (C). -| The result of a complexity measure shall have as outcome [NH, HM, NM] -| - NH: Not High -| - HM: High but Manageable -| - NM: high and Not Manageable -| -| **Complexity measure for programming language: <C++ or RUST>** - -<select the correct table below (table for C++ is TBD)> - -.. list-table:: Determine (C) for RUST - :header-rows: 1 - - * - Id - - Indicator for high Complexity - - Complexity measure Tool - - Result - - Number - - * - 1 - - High amount of Lines of Code - - Lines of Code (without comments) (generated code is excluded, e.g. ProtoCmpl) - - <NH|HM|NM> - - <Number> - - * - 2 - - Unsafe code used / total unsafe code - - Count: - * LoUC+N: lines of unsafe code with safety note - * LoUC : lines of unsafe code, no safety note - - <NH|HM|NM> - - <Number> - - * - 3 - - | Test exists / Coverage (Function, Line) - | (maybe better: testability, but how to measure?) - - Existing Tests Coverage - - <NH|HM|NM> - - <Number> - - * - 4 - - High amount of public function interfaces - - Number of public function interfaces - - <NH|HM|NM> - - <RNumber> - - * - 5 - - High amount of function parameters - - Number of parameters - - <NH|HM|NM> - - <Number> - - -| (C=1) shall be selected when none of the determined complexity measures indicate HM or NM. -| (C=2) shall be selected when at least one of the determined complexity measures indicate HM or NM, but the gaps evaluated are acceptable, means -| the risk of systematic faults due to these gaps is sufficiently low in the context of S-CORE or manageable by mitigating the gaps. -| (C=3) in all other cases. -| - -<component name> is determined as C=<1|2|3> - - -Step 3: Determine (CLAS_OUT): the classification outcome --------------------------------------------------------- - -| Select CLAS_OUT depending on the determined values of (C) and (P) - -+-------+-----------------------+ -| ( C ) | ( P ) | -+-------+-------+-------+-------+ -| | 1 | 2 | 3 | -+=======+=======+=======+=======+ -| 1 | Q | Q | QR | -+-------+-------+-------+-------+ -| 2 | QR | QR | QR | -+-------+-------+-------+-------+ -| 3 | QR | QR | NQ | -+-------+-------+-------+-------+ - -<component name> is classified as CLAS_OUT=<Q|QR|NQ> - - -Step 4: Document all results and rationale for choosing (P) and (C) and (CLAS_OUT) ----------------------------------------------------------------------------------- -This document - - -Step 5: Based on (CLAS_OUT) select the activities -------------------------------------------------- - -| As soon as the change request containing this is in status "Accepted", the module safety plan for the component development is adapted based on the following: (select according to above result) -| - Q: Follow the processes for qualification of software components in a safety context. -| - QR: Follow the process for pre-existing software architectural elements -| - NQ: Do no use this element in safety context diff --git a/docs/modules/persistency/kvs/docs/index.rst b/docs/modules/persistency/kvs/docs/index.rst deleted file mode 100644 index 5cc5ee50fd..0000000000 --- a/docs/modules/persistency/kvs/docs/index.rst +++ /dev/null @@ -1,180 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _component_PersistencyKvs: - -KVS (Key Value Store) -##################### - -.. note:: Document header - -.. document:: Persistency KVS - :id: doc__persistencykvs - :status: draft - :safety: ASIL_B - :realizes: wp__cmpt_request - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``document`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Abstract -======== - -[A short (~200 word) description of the contribution being addressed.] - - -Motivation -========== - -[Clearly explain why the existing platform/project solution is inadequate to address the topic that the CR solves.] - - .. note:: - The motivation is critical for CRs that want to change the existing components. - It should clearly explain why the existing solution is inadequate to address the topic that the CR solves. - Motivation may based on criteria as resource requirements, scheduling issues, risks, benefits, etc. - CRs submissions without sufficient motivation may be rejected. - - - -Rationale -========= - -[Describe why particular design decisions were made.] - - - .. note:: - The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. - - -Specification -============= - -[Describe the requirements, architecture of any new component.] or -[Describe the change to requirements, architecture, implementation, documentation of any change request.] - - .. note:: - A CR shall specify the component requirements as part of our platform/project. - Thereby the :need:`PROCESS_rl__module_lead` will approve these requirements as part of accepting the CR (e.g. merging the PR with the CR). - - - -Backwards Compatibility -======================= - -[Describe potential impact (especially including safety and security impacts) and severity on pre-existing platform/project elements.] - - -Security Impact -=============== - -[How could a malicious user take advantage of this new/modified component?] - - .. note:: - If there are security concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which security requirements are affected or has to be changed? -Could the new/modified component enable new threat scenarios? -Could the new/modified component enable new attack paths? -Could the new/modified component impact functional safety? -If applicable, which additional security measures must be implemented to mitigate the risk? - - .. note:: - Use Security Software Critically Analysis, Vulnerability Analysis. - [Methods will be defined later in Process area Security Analysis] - - -Safety Impact -============= - -[How could the safety be impacted by the new/modified component?] - - .. note:: - If there are safety concerns in relation to the CR, those concerns should be explicitly written out to make sure reviewers of the CR are aware of them. - -Which safety requirements are affected or has to be changed? -Could the new/modified component be a potential common cause or cascading failure initiator? -If applicable, which additional safety measures must be implemented to mitigate the risk? - - .. note:: - Use Dependency Failure Analysis and/or Safety Software Critically Analysis. - [Methods will be defined later in Process area Safety Analysis] - -For new feature/component contributions: - -[What is the expected ASIL level?] -[What is the expected classification of the contribution?] - - .. note:: - Use the component classification method here to classify your component, if it shall to be used in a safety context: :need:`PROCESS_gd_temp__component_classification`. - -License Impact -============== - -[How could the copyright impacted by the license of the new contribution?] - - -How to Teach This -================= - -[How to teach users, new and experienced, how to apply the CR to their work.] - - .. note:: - For a CR that adds new functionality or changes behavior, it is helpful to include a section on how to teach users, new and experienced, how to apply the CR to their work. - - - -Rejected Ideas -============== - -[Why certain ideas that were brought while discussing this CR were not ultimately pursued.] - - .. note:: - Throughout the discussion of a CR, various ideas will be proposed which are not accepted. - Those rejected ideas should be recorded along with the reasoning as to why they were rejected. - This both helps record the thought process behind the final version of the CR as well as preventing people from bringing up the same rejected idea again in subsequent discussions. - In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. - - - -Open Issues -=========== - -[Any points that are still being decided/discussed.] - - .. note:: - While a CR is in draft, ideas can come up which warrant further discussion. - Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. - This helps make sure all issues required for the CR to be ready for consideration are complete and reduces people duplicating prior discussion. - - - -Footnotes -========= - -[A collection of footnotes cited in the CR, and a place to list non-inline hyperlink targets.] - -.. toctree:: - :hidden: - - requirements/index.rst - architecture/index.rst - safety_analysis/fmea.rst - safety_analysis/dfa.rst - component_classification.rst diff --git a/docs/modules/persistency/kvs/docs/requirements/index.rst b/docs/modules/persistency/kvs/docs/requirements/index.rst deleted file mode 100644 index 3c7caf8e7a..0000000000 --- a/docs/modules/persistency/kvs/docs/requirements/index.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Component Requirements -###################### - -.. comp_req:: Key Handling - :id: comp_req__persistency__key_handling - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__support_datatype_keys - :status: valid - - The component shall accept keys that consist solely of alphanumeric characters, underscores, or dashes. - The component shall encode each key as valid UTF-8. - The component shall guarantee that each key is unique. - The component shall limit the maximum length of a key to 32 bytes. - -.. comp_req:: Value Handling - :id: comp_req__persistency__value_handling - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__support_datatype_value,feat_req__persistency__default_values - :status: valid - - The component shall accept only values of the following data types: Number, String, Null, Array[Value], or Dictionary{Key:Value}. - The component shall serialize and deserialize all values to and from JSON. - The component shall limit the maximum length of a value to 1024 bytes. - The component shall support unset values and shall provide a default value when a value is unset. - The component shall allow resetting a value to its default if a default is defined. - -.. comp_req:: Default Value Handling - :id: comp_req__persistency__default_value_handling - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__default_values,feat_req__persistency__default_value_get,feat_req__persistency__default_value_reset,feat_req__persistency__default_value_file - :status: valid - - The component shall accept default values of only permitted value data types. - The component shall provide an API to retrieve default values. - The component shall allow configuration of default values in code or in a separate configuration file. - The component shall secure the configuration file for default values with an associated checksum file when default values are stored in a file. - -.. comp_req:: Constraint Configuration - :id: comp_req__persistency__constraints - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__config_file - :status: valid - - The component shall allow configuration of KVS constraints at compile-time using source code constants or at runtime using a configuration file. - -.. comp_req:: Language Agnostic - :id: comp_req__persistency__language_agnostic - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__cpp_rust_interop - :status: valid - - The component shall provide an API that supports bindings to other languages or shall use a storage and memory exchange format that is adaptable to other languages. - -.. comp_req:: Concurrency - :id: comp_req__persistency__concurrency - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__intra_process_comm - :status: valid - - The component shall implement thread-safe mechanisms to enable concurrent access to data without data races. - -.. comp_req:: Multi-Instance - :id: comp_req__persistency__multi_instance - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__multiple_kvs - :status: valid - - The component shall manage all runtime variables within an instance to enable creation and use of multiple KVS instances concurrently within a single software architecture element. - -.. comp_req:: Persistent Data Storage - :id: comp_req__persistency__persist_data_storage - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__persist_data - :status: valid - - The component shall use the file API and the JSON data format to persist data. - The component shall generate a checksum for each data file and shall store it alongside the data. - The component shall verify the checksum when loading data. - -.. comp_req:: Persistent Data Schema Handling - :id: comp_req__persistency__persistent_data_schema - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__versioning,feat_req__persistency__update_mechanism - :status: valid - - The component shall not provide built-in versioning. - The component shall use a JSON file storage format that enables the application to implement versioning, including upgrade and downgrade paths, as needed. - -.. comp_req:: Snapshots - :id: comp_req__persistency__snapshots - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__snapshots - :status: valid - - The component shall create a snapshot each time data is stored. - The component shall maintain a configurable maximum number of snapshots. - The component shall assign the ID 1 to the newest snapshot and shall increment the IDs of older snapshots accordingly. - The component shall rotate and delete the oldest snapshot when the maximum number is reached. - The component shall allow restoration of a snapshot by its ID. - The component shall allow deletion of individual snapshots. - -.. comp_req:: Develop Mode - :id: comp_req__persistency__dev_mode - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__dev_mode - :status: valid - - The component shall provide a developer mode that can be enabled during build time to display debugging and internal information. - -.. comp_req:: Async API - :id: comp_req__persistency__async_api - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__async_api - :status: valid - - The component shall provide an asynchronous API in addition to the standard API. - -.. comp_req:: Permission Handling - :id: comp_req__persistency__permission_handling - :reqtype: Functional - :security: NO - :safety: QM - :satisfies: feat_req__persistency__access_control - :status: valid - - The component shall rely on the underlying filesystem for access and permission management and shall not implement its own access or permission controls. - The component shall report any access or permission errors encountered at the filesystem level to the application. - -.. comp_req:: Callback Support - :id: comp_req__persistency__callback_support - :reqtype: Functional - :security: NO - :safety: ASIL_B - :satisfies: feat_req__persistency__events - :status: valid - - The component shall provide an API for registering callbacks that are triggered by data change events. diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst b/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst deleted file mode 100644 index be4e82b4b1..0000000000 --- a/docs/modules/persistency/kvs/docs/safety_analysis/dfa.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - - -Dependent Failure Analysis -========================== - -.. document:: KVS DFA - :id: doc__kvs_dfa - :status: valid - :safety: ASIL_B - :realizes: wp__sw_component_dfa - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_dfa`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Dependent Failure Intitiators ------------------------------ - -.. code-block:: rst - - .. comp_saf_dfa:: <Element descriptor> - :id: comp_saf_DFA__<Component>__<Element descriptor> - :violation_id: <ID from Dependent Failure Initiators list :need:`gd_guidl__dfi`> - :violation_effect: <Effect caused by the initiator (leading to a violation of a safety goal)> - :verifies: <ID from Component Architecture> - :mitigated_by: < NONE|ID from Component Requirement> - :sufficient: <yes|no> - :argument: <text to argument why measure is sufficient> - :status: <valid|invalid> - -.. attention:: - The above directive must be updated according to your component DFA. - - - Remove the ``code-block`` - - Fill in all the needed information in the <brackets> diff --git a/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst b/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst deleted file mode 100644 index 7a5c4eccc8..0000000000 --- a/docs/modules/persistency/kvs/docs/safety_analysis/fmea.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - - -Safety Analysis : FMEA -====================== - -.. document:: KVS FMEA - :id: doc__kvs_fmea - :status: valid - :safety: ASIL_B - :realizes: wp__sw_component_safety_analysis - :tags: template - -.. attention:: - The above directive must be updated according to your Component. - - - Modify ``Your Component Name`` to be your Component Name - - Modify ``id`` to be your Component Name in upper snake case preceded by ``doc__`` and succeeded by ``_fmea`` - - Adjust ``status`` to be ``valid`` - - Adjust ``safety`` and ``tags`` according to your needs - -Failure Mode List ------------------ - -.. code-block:: rst - - .. comp_saf_fmea:: <Element descriptor> - :id: comp_saf_FMEA__<Component>__<Element descriptor> - :failure_mode: <ID from fault model :need:`gd_guidl__fault_models`> - :failure_effect: <Effect caused by the failure (leading to a violation of a safety goal)> - :verifies: <ID from Component Architecture> - :mitigated_by: < NONE|ID from Component Requirement> - :sufficient: <yes|no> - :argument: <text to argument why measure is sufficient> - :status: <valid|invalid> - -.. attention:: - The above directive must be updated according to your component FMEA. - - - Remove the ``code-block`` - - Fill in all the needed information in the <brackets> From ee6c967b0e3dcea51e6484597ae67fb3c00ca20f Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Fri, 6 Jun 2025 08:59:28 +0200 Subject: [PATCH 038/102] persistency_kvs: re-add missing Persistency main topic to KVS Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- docs/features/persistency/index.rst | 120 +--------------- docs/features/persistency/kvs/index.rst | 131 ++++++++++++++++++ .../{ => kvs}/requirements/index.rst | 0 3 files changed, 137 insertions(+), 114 deletions(-) create mode 100644 docs/features/persistency/kvs/index.rst rename docs/features/persistency/{ => kvs}/requirements/index.rst (100%) diff --git a/docs/features/persistency/index.rst b/docs/features/persistency/index.rst index 5f7c87169a..019f7e14b3 100644 --- a/docs/features/persistency/index.rst +++ b/docs/features/persistency/index.rst @@ -12,120 +12,12 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Key-Value-Storage -################# - -.. document:: Persistency Key-Value-Storage - :id: doc__persistency_kvs - :status: valid - :safety: ASIL_B - :tags: feature_request, persistency_kvs +Persistency +########### .. toctree:: - requirements/index.rst - - -Feature flag -============ - -To activate this feature, use the following feature flag: - -``persistency_kvs`` - - -Abstract -======== - -This feature request describes the key-value storage (KVS) that is needed by -applications to store either temporary or permanent data in an easy way that -conforms to most programming languages that provide a hash, hashmap, dictionary -or similar data structure. Access to the KVS is possible from any support -language through language specific interfaces. - - -Motivation -========== - -The current solutions available mostly don't meet the specific needs of the -S-CORE project like storing specific datatypes without a BASE64 conversation or -having no rollback/replay feature. Also the integration into analysis tools is -simpler when the solution grows with the needs instead having to adapt existing -data structures through wrapppers. Especially in the focus of security it will -be possible to build a system that integrates the layers from scratch and -provide them as API to any language whilst still using Rust as the backend. - -A main USP of the solution will be the integration of a tracing framework that -allows to understand how events also in the context of other events interact. - -A key-value storage is used within many applications to store e.g. -configuration data and is therefore seen crucial for the Eclipse S-CORE -platform. - - -Rationale -========= - -1. | Requirement 1: Multiple key-value storages per application - | Solution: Allow each application to have multiple key-value storages (KVS) to enable data separation and different levels of security. -2. | Requirement 2: Update mechanism for KVS versions - | Solution: Implement an update mechanism to ensure compatibility through updates and rollbacks of different KVS versions. -3. | Requirement 3: Language-agnostic KVS interface - | Solution: Design a flexible interface that allows the KVS to be read and written from multiple programming languages, including C++, Rust, and others. -4. | Requirement 4: Default values for KVS - | Solution: Configure the KVS to store default values for all keys, returning either the default value or an error if the key needs to be written first. -5. | Requirement 5: Simple data representation for KVS - | Solution: Utilize a simple data representation, such as JSON or Cap'n Proto, that supports versioned up- and downgrading and is easily debuggable by developers. -6. | Requirement 6: KVS integrity checking - | Solution: Ensure the KVS maintains a consistent state, providing either the currently stored data or the previous snapshot if data retrieval is not possible. - -Backwards Compatibility -======================= - -The API for the specific language tries to represent the language specific -implementation like hashmaps or dictionaries to be mostly backwards compatible -to already existing key-value-storage usage cases. Access without a safe error -handling path, like the array-operator in Rust which can panic, must be -avoided. - - -Security Impact -=============== - -Access to the key-value-storage would allow a malicious user to control the -behaviour of the device, so it must be secured to prevent unauthorized access. -To achieve this, debug access should only be provided when a debug firmware -image is installed. - - -Safety Impact -============= - -The expected ASIL level is ASIL-B. To reach this goal we will apply the S-CORE -development process. Key elements of it are listed in the process descriptions -of safety management and safety analysis. In the safety analysis we will -analyze the impact of the feature. - - .. note:: - TODO: Link to safety analysis. - -We use an iterative development process and apply results from the next steps -back to the feature request. For TinyJSON we will perform a software component -classification. - - .. note:: - TODO: Link to component classification. - -To ensure the freedom of interference the feature key-value storage should not -be used within different processes. - - -License Impact -============== - - .. note:: - The key-value storage itself uses the Apache-2.0 license. Licenses of - used libraries are need to be checked. - + :maxdepth: 1 + :glob: + :titlesonly: -How to Teach This -================= + */index diff --git a/docs/features/persistency/kvs/index.rst b/docs/features/persistency/kvs/index.rst new file mode 100644 index 0000000000..5f7c87169a --- /dev/null +++ b/docs/features/persistency/kvs/index.rst @@ -0,0 +1,131 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Key-Value-Storage +################# + +.. document:: Persistency Key-Value-Storage + :id: doc__persistency_kvs + :status: valid + :safety: ASIL_B + :tags: feature_request, persistency_kvs + +.. toctree:: + requirements/index.rst + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``persistency_kvs`` + + +Abstract +======== + +This feature request describes the key-value storage (KVS) that is needed by +applications to store either temporary or permanent data in an easy way that +conforms to most programming languages that provide a hash, hashmap, dictionary +or similar data structure. Access to the KVS is possible from any support +language through language specific interfaces. + + +Motivation +========== + +The current solutions available mostly don't meet the specific needs of the +S-CORE project like storing specific datatypes without a BASE64 conversation or +having no rollback/replay feature. Also the integration into analysis tools is +simpler when the solution grows with the needs instead having to adapt existing +data structures through wrapppers. Especially in the focus of security it will +be possible to build a system that integrates the layers from scratch and +provide them as API to any language whilst still using Rust as the backend. + +A main USP of the solution will be the integration of a tracing framework that +allows to understand how events also in the context of other events interact. + +A key-value storage is used within many applications to store e.g. +configuration data and is therefore seen crucial for the Eclipse S-CORE +platform. + + +Rationale +========= + +1. | Requirement 1: Multiple key-value storages per application + | Solution: Allow each application to have multiple key-value storages (KVS) to enable data separation and different levels of security. +2. | Requirement 2: Update mechanism for KVS versions + | Solution: Implement an update mechanism to ensure compatibility through updates and rollbacks of different KVS versions. +3. | Requirement 3: Language-agnostic KVS interface + | Solution: Design a flexible interface that allows the KVS to be read and written from multiple programming languages, including C++, Rust, and others. +4. | Requirement 4: Default values for KVS + | Solution: Configure the KVS to store default values for all keys, returning either the default value or an error if the key needs to be written first. +5. | Requirement 5: Simple data representation for KVS + | Solution: Utilize a simple data representation, such as JSON or Cap'n Proto, that supports versioned up- and downgrading and is easily debuggable by developers. +6. | Requirement 6: KVS integrity checking + | Solution: Ensure the KVS maintains a consistent state, providing either the currently stored data or the previous snapshot if data retrieval is not possible. + +Backwards Compatibility +======================= + +The API for the specific language tries to represent the language specific +implementation like hashmaps or dictionaries to be mostly backwards compatible +to already existing key-value-storage usage cases. Access without a safe error +handling path, like the array-operator in Rust which can panic, must be +avoided. + + +Security Impact +=============== + +Access to the key-value-storage would allow a malicious user to control the +behaviour of the device, so it must be secured to prevent unauthorized access. +To achieve this, debug access should only be provided when a debug firmware +image is installed. + + +Safety Impact +============= + +The expected ASIL level is ASIL-B. To reach this goal we will apply the S-CORE +development process. Key elements of it are listed in the process descriptions +of safety management and safety analysis. In the safety analysis we will +analyze the impact of the feature. + + .. note:: + TODO: Link to safety analysis. + +We use an iterative development process and apply results from the next steps +back to the feature request. For TinyJSON we will perform a software component +classification. + + .. note:: + TODO: Link to component classification. + +To ensure the freedom of interference the feature key-value storage should not +be used within different processes. + + +License Impact +============== + + .. note:: + The key-value storage itself uses the Apache-2.0 license. Licenses of + used libraries are need to be checked. + + +How to Teach This +================= diff --git a/docs/features/persistency/requirements/index.rst b/docs/features/persistency/kvs/requirements/index.rst similarity index 100% rename from docs/features/persistency/requirements/index.rst rename to docs/features/persistency/kvs/requirements/index.rst From 9b56d81f780e1413e6aa9bbba46cf0342725fc00 Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Thu, 5 Jun 2025 08:55:17 +0200 Subject: [PATCH 039/102] persistency_kvs: re-add feature architecture Signed-off-by: Sven Bachmann <sven.bachmann.ext@qorix.ai> --- .../architecture/_assets/kvs_dyn_builder.puml | 25 ++++ .../_assets/kvs_dyn_check_value_default.puml | 24 ++++ .../_assets/kvs_dyn_delete_data_key.puml | 16 +++ .../kvs_dyn_flush_local_repr_to_file.puml | 56 ++++++++ .../_assets/kvs_dyn_read_data_key.puml | 20 +++ .../kvs_dyn_read_file_into_local_repr.puml | 47 +++++++ .../_assets/kvs_dyn_restore_snapshot.puml | 16 +++ .../_assets/kvs_dyn_write_data_key.puml | 11 ++ .../architecture/_assets/kvs_interface.puml | 21 +++ .../architecture/_assets/kvs_static_view.puml | 34 +++++ .../persistency/kvs/architecture/index.rst | 129 ++++++++++++++++++ docs/features/persistency/kvs/index.rst | 1 + 12 files changed, 400 insertions(+) create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml create mode 100644 docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml create mode 100644 docs/features/persistency/kvs/architecture/index.rst diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml new file mode 100644 index 0000000000..a1b25fe473 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_builder.puml @@ -0,0 +1,25 @@ +@startuml + +title Sequence Diagram: Build KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Create KVS builder +kvs --> actor: KVS builder instance + +actor -> kvs: Set need_defaults flag +kvs --> actor: KVS builder instance + +actor -> kvs: Set need_kvs flag +kvs --> actor: KVS builder instance + +actor -> kvs: Build KVS instance + +alt kvs-builder-success + kvs --> actor: KVS instance with builder config +else kvs-builder-error + kvs --> actor: KVS ErrorCode +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml new file mode 100644 index 0000000000..01baa2727f --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_check_value_default.puml @@ -0,0 +1,24 @@ +@startuml + +title Sequence Diagram: Check if Key contains Default Value + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Does key have default value + +alt default-key-exists + alt key-exists + alt default-and-key-match + kvs --> actor: Key contains default value + else key-doesnt-exist + kvs --> actor: Key doesn't containt default value + end + else key-doesnt-exist + kvs --> actor: Key contains default value + end +else default-doesnt-exist + kvs --> actor: Key doesn't contain default value +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml new file mode 100644 index 0000000000..e2b222e311 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_delete_data_key.puml @@ -0,0 +1,16 @@ +@startuml + +title Sequence Diagram: Delete Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Remove key + +alt key-exists + kvs --> actor: Successfully deleted key +else key-doesnt-exist + kvs --> actor: Key-Not-Found-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml new file mode 100644 index 0000000000..947cf782eb --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_flush_local_repr_to_file.puml @@ -0,0 +1,56 @@ +@startuml + +title Sequence Diagram: Flush Local Representation to Data File + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :json" as json_parser +participant "«component» :fs" as fs + +actor -> kvs: Flush KVS + +kvs -> json_parser: Generate string from local representation + +alt json-string + json_parser --> kvs: JSON data string +else json-string-error + json_parser --> kvs: JSON generator error + kvs --> actor: JSON generator error +end + +kvs -> kvs: Rotate snapshots + +alt snapshot-rotate-success + kvs --> kvs: Snapshots rotated +else snapshot-rotate-error + kvs --> actor: Snapshot-Rotate-Error +end + +kvs -> kvs: Create JSON data hash + +alt hash-created-success + kvs -> kvs: Data hash +else hash-create-error + kvs --> actor: Hash-Calc-Error +end + +kvs -> fs: Write JSON data string to file + +alt file-write + fs --> kvs: File successfully written +else file-write-error + fs --> kvs: File-Write-Error + kvs --> actor: File-Write-Error +end + +kvs -> fs: Write JSON data hash to file + +alt file-hash-write + fs --> kvs: Hash file successfully written + kvs --> actor: Flush successful +else file-hash-write-error + fs --> kvs: File-Hash-Write-Error + kvs --> actor: File-Hash-Write-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml new file mode 100644 index 0000000000..064e248911 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_data_key.puml @@ -0,0 +1,20 @@ +@startuml + +title Sequence Diagram: Read Key from KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Get value for key + +alt key-exists + kvs --> actor: Return value for key +else key-doesnt-exist + alt default-exists + kvs --> actor: Return default value for key + else default-doesnt-exist + kvs --> actor: Key-Not-Found error + end +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml new file mode 100644 index 0000000000..4a154d24df --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_read_file_into_local_repr.puml @@ -0,0 +1,47 @@ +@startuml + +title Sequence Diagram: Read Data into Local Representation (KvsValue) + +participant "User" as actor +participant "«component» :kvs" as kvs +participant "«component» :json" as json_parser +participant "«component» :fs" as fs + +actor -> kvs: Open KVS + +kvs -> fs: Read defaults file + +alt file-exists + fs --> kvs: Defaults file content (JSON) +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> fs: Read defaults file hash + +alt file-exists + fs --> kvs: Defaults file hash +else file-based-error + fs --> kvs: File-Error + kvs -> actor: File-Error +end + +kvs -> kvs: Generate defaults file hash + +alt hash-match-success + kvs -> json_parser: Parse JSON data +else hash-match-error + kvs -> actor: Hash-Error +end + +alt parsing-success + json_parser --> kvs: Parsed JSON object +else parsing-based-error + json_parser -> kvs: Parser-Error + kvs -> actor: Parser-Error +end + +kvs --> actor: KVS instance + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml new file mode 100644 index 0000000000..17eb75b382 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_restore_snapshot.puml @@ -0,0 +1,16 @@ +@startuml + +title Sequence Diagram: Restore Snapshot + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Restore snapshot + +alt snapshot-restore-success + kvs --> actor: Snapshot restored successfully +else snapshot-restore-error + kvs --> actor: Snapshot-Not-Available-Error +end + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml new file mode 100644 index 0000000000..b34c24cc20 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_dyn_write_data_key.puml @@ -0,0 +1,11 @@ +@startuml + +title Sequence Diagram: Write Key to KVS Instance + +participant "User" as actor +participant "«component» :kvs" as kvs + +actor -> kvs: Set value for key +kvs --> actor: Value set for key + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml new file mode 100644 index 0000000000..46f65a27cc --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_interface.puml @@ -0,0 +1,21 @@ +@startuml + +interface IKvs { + open + flush_on_exit + reset + get_all_keys + key_exists + get_value + get_default_value + has_default_value + set_default_value + set_value + remove_key + flush + snapshot_count + snapshot_max_count + snapshot_restore +} + +@enduml diff --git a/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml new file mode 100644 index 0000000000..ebb646f285 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/_assets/kvs_static_view.puml @@ -0,0 +1,34 @@ +@startuml +allowmixing + +title Static View - kvs + +!include kvs_interface.puml + + +skinparam package { + BackgroundColor #E0E0D0 + BorderColor Black + backgroundColor<<module>> lightgreen +} + +skinparam component { + backgroundColor<<component>> white +} + +' Define Features +package "persistency" <<module>> { + component kvs <<component>> + component fs <<component>> + component json <<component>> +} + + + +kvs --> IKvs : implements + +kvs ..> json : use +kvs ..> fs : use + + +@enduml diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst new file mode 100644 index 0000000000..21ee05d945 --- /dev/null +++ b/docs/features/persistency/kvs/architecture/index.rst @@ -0,0 +1,129 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Architecture : persistency/kvs +====================================== + +Overview +-------- + +- kvs provides the capability to efficiently store, retrieve, and + manage key-value pairs in a persistent storage system. + +Description +----------- + +- kvs organize data as pairs, where each unique key is associated with a specific value. + The key acts as a unique identifier for getting the value. +- The data is persisted in JSON format to the file system, providing a human-readable, + and widely supported way to store and manage key-value pairs. +- The JSON data persisted is according to RFC-8259. + +Rationale Behind Architecture Decomposition +******************************************* + +- The architecture is decomposed to include a dedicated JSON parser component (json) to facilitate the persistent storage of data in JSON format. +- The architecture is decomposed to include a FileStorage component (fs) to read and write to the file system. + + +Static Architecture +------------------- + +.. feat_arc_sta:: Static Architecture + :id: feat_arc_sta__persistency__static + :security: YES + :safety: ASIL_B + :includes: logic_arc_int__persistency__interface + :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value + :status: valid + + .. uml:: _assets/kvs_static_view.puml + +Dynamic Architecture +-------------------- +.. feat_arc_dyn:: Check if key contains default value + :id: feat_arc_dyn__persistency__check_key_default + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__default_values,feat_req__persistency__default_value_get + :status: valid + + .. uml:: _assets/kvs_dyn_check_value_default.puml + +.. feat_arc_dyn:: Delete key from KVS instance + :id: feat_arc_dyn__persistency__delete_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__events + :status: valid + + .. uml:: _assets/kvs_dyn_delete_data_key.puml + +.. feat_arc_dyn:: Flush to permanent storage + :id: feat_arc_dyn__persistency__flush + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__integrity_check,feat_req__persistency__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_flush_local_repr_to_file.puml + +.. feat_arc_dyn:: Read key value + :id: feat_arc_dyn__persistency__read_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value,feat_req__persistency__default_values,feat_req__persistency__default_value_get + :status: valid + + .. uml:: _assets/kvs_dyn_read_data_key.puml + +.. feat_arc_dyn:: Read data from permanent storage + :id: feat_arc_dyn__persistency__read_from_storage + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__integrity_check,feat_req__persistency__snapshots + :status: valid + + .. uml:: _assets/kvs_dyn_read_file_into_local_repr.puml + +.. feat_arc_dyn:: Write value to key + :id: feat_arc_dyn__persistency__write_key + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value + :status: valid + + .. uml:: _assets/kvs_dyn_write_data_key.puml + +.. feat_arc_dyn:: Restore snapshot + :id: feat_arc_dyn__persistency__snapshot_restore + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__snapshots,feat_req__persistency__persist_data,feat_req__persistency__persistency + :status: valid + + .. uml:: _assets/kvs_dyn_restore_snapshot.puml + + +Logical Interfaces +------------------ + +.. logic_arc_int:: Ikvs + :id: logic_arc_int__persistency__interface + :security: YES + :safety: ASIL_B + :fulfils: feat_req__persistency__stable_api + :status: valid + + .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/index.rst b/docs/features/persistency/kvs/index.rst index 5f7c87169a..290937da5a 100644 --- a/docs/features/persistency/kvs/index.rst +++ b/docs/features/persistency/kvs/index.rst @@ -23,6 +23,7 @@ Key-Value-Storage .. toctree:: requirements/index.rst + architecture/index.rst Feature flag From e2952b676cd6103b9d284c94a9495acaef773add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Fri, 13 Jun 2025 08:30:31 +0200 Subject: [PATCH 040/102] fix docs commands docu in README (#1233) --- README.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0855b10586..fe4f3d2c77 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,20 @@ Score supports multiple methods for generating documentation, tailored to differ This method ensures clean and isolated documentation builds in a controlled Bazel environment. It is best suited for CI pipelines or production-ready outputs, although it takes longer compared to incremental builds. +Here it is possible to build it either with the current 'main' branch of [process](https://github.com/eclipse-score/process_description) or with the imported release version of it. + + +> Note: 'latest' might not work if it's executed behind a proxy or vpn. If this is the case please use 'release' + ```sh -bazel build //docs:docs +bazel build //docs:docs_latest # use current main branch of imported docs repositories (e.g. process_description) +bazel build //docs:docs_release # use release version imported in MODULE.bazel ``` -The output will be located in bazel-bin/docs/docs/_build/html. +The output will be located here,depending on which way was chosen: +- bazel-bin/docs/docs_latest/_build/html. +- bazel-bin/docs/docs_release/_build/html. + #### Incremental build @@ -48,7 +57,8 @@ For local changes and faster feedback, use the incremental build. This method generates the documentation directly in the _build directory. ```sh -bazel run //docs:incremental +bazel run //docs:incremental_latest # use current main branch of imported docs repositories (e.g. process_description) +bazel run //docs:incremental_release # use release version imported in MODULE.bazel ``` Unlike IDE integration, which renders only the current file, this approach is ideal for quickly verifying edits across the entire documentation during development. @@ -77,9 +87,10 @@ Re-run //docs:ide_support if you update Sphinx extensions or other dependencies. For a documentation live preview independent of an IDE (CLI + browser only), `sphinx-autobuild` can be used. This will automatically rebuild the preview after save and have it available at http://127.0.0.1:8000 - +Release and latest are both available here as well. ```sh -bazel run //docs:live_preview +bazel run //docs:live_preview_latest # use current main branch of imported docs repositories (e.g. process_description) +bazel run //docs:live_preview_release # use release version imported in MODULE.bazel ``` @@ -131,10 +142,13 @@ sudo apt install lcov ### Notes #### Output Locations -* Bazel builds output to bazel-bin/docs/docs/_build/html. -* Incremental builds output to _build. +* Bazel builds output, depending on which build was chosen: + - bazel-bin/docs/docs_latest/_build/html. + - bazel-bin/docs/docs_release/_build/html. +* Incremental builds output to _build, regardless of chosen way. #### Troubleshooting * Restart your IDE if live previews or warnings are not working after running ide_support. * Ensure your virtual environment is up-to-date by re-running //docs:ide_support when dependencies change. +* Ensure you ran //docs:ide_support before executing //:format.check or //:format.fix From f99e41ca8992a7e98367901d27d216e82500a1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20H=C3=A4ussler?= <volker.haeussler@qorix.ai> Date: Sat, 7 Jun 2025 12:49:32 +0200 Subject: [PATCH 041/102] process: update quality managemen plan Ref: closes #1210 --- docs/platform_management_plan/index.rst | 1 - .../quality_management.rst | 897 +++++++++++++++++- .../requirements_management.rst | 25 - .../safety_management.rst | 2 +- 4 files changed, 892 insertions(+), 33 deletions(-) delete mode 100644 docs/platform_management_plan/requirements_management.rst diff --git a/docs/platform_management_plan/index.rst b/docs/platform_management_plan/index.rst index 6d6830bdd1..08eca73249 100644 --- a/docs/platform_management_plan/index.rst +++ b/docs/platform_management_plan/index.rst @@ -36,7 +36,6 @@ Platform Management Plan release_management problem_resolution change_management - requirements_management software_verification documentation_management software_development diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index 26790b4b81..c207847c31 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -12,14 +12,899 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Quality management ------------------------- +Quality Management / Platform Quality Management Plan +===================================================== + +.. document:: Platform Quality Management Plan + :id: doc__platform_quality_plan + :status: valid + :safety: ASIL_B + :realizes: wp__qms_plan + :tags: platform_management Purpose -+++++++ +------- + +The purpose of this document is to is to define a quality strategy and an approach for the platform. +This includes an approach to providing an independent and objective assurance that work products and processes +comply with predefined provisions and plans and that non-conformances are resolved and further prevented. +This document includes quality assurance activities, roles and responsibilities, goals, schedule, etc. and a +general strategy to implement a quality assurance process in this platform. The quality assurance is +ensured by automated checks and restrictions, manual checks which inculdes to proof that there is no manipulation +of the workflows. + +Statement of Independence +------------------------- + +There could be a conflict of interest between the project lead :need:`PROCESS_rl__project_lead` and the quality manager +:need:`PROCESS_rl__quality_manager`, as both roles are responsible for the project. The project lead is responsible for +the project and the quality manager is responsible for the quality of the project. + +Therefore we define that the quality manager only support the project with consulting. So the project itself +shall improve the quality of the project/platform product. The combination of both shall found the best solution +for the project. The quality report is sent to the :need:`PROCESS_rl__technical_lead` so that conflicts can be solved +in the steering committees. + +The objectives and scope of the quality management, also the measures and checklists are transparent for everyone. +So the project itself can improve the quality of the project/platform product with the support of the knowledge of +the quality manager. Objectives and scope -++++++++++++++++++++ +-------------------- + +3.1 Quality Objectives +^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: Standards to comply with + :header-rows: 1 + :widths: 15,85,15 + + * - # + - **Standard Name** + - **Version** + * - 1 + - Automotive SPICE PAM + - 4.0 + * - 2 + - ISO 262626:2018 + - 2018 + * - 3 + - ISO/SAE 21434:2021 + - 2021 + * - 4 + - ISO PAS 8926:2024 + - 2024 + + +3.2 Quality Performance Objectives +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: Quality assurance activities and frequence of performing them + :header-rows: 1 + + * - # + - **Activities** + - **Cadence** + * - 1 + - Platform Process audit + - Once for every platform release or on demand + * - 2 + - Feature Process compliance checks + - Once for every feature release + * - 3 + - Feature Work product review + - Once for every feature release + * - 4 + - Platform Release verification and approval + - Once for every release + * - 5 + - Process consulting / Quality Trainings + - Continuously + * - 6 + - Process monitoring / Process Improvement + - Continuously + + +3.3 Quantitative Quality Goals +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: Quantitative Quality Goals + :header-rows: 1 + + * - # + - **Quality Criteria** + - **Source** + - **Target value** + - **Allowed variation** + - **Metric** + * - 1 + - One platform process audit per release + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - 100% of the platform process audit has be done for every release + - Delta audit allowed to achieve 100% + - Ensured by the process process management, :need:`PROCESS_wp__process_impr_report` - Platform process audit is available + * - 2 + - One process conformance check for every feature release + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - One process conformance check has been done for every stable feature release + - Feature is released as experimental + - Ensured by the process quality and tool management, :need:`PROCESS_wp__qms_report` - Process conformance is available + * - 3 + - Only quality-assured project/platform work products are delivered to the community + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - 100% of project/platform work products are quality-assured + - Feature is released as experimental + - Ensured by the process quality and tool management, :need:`PROCESS_wp__verification__platform_ver_report` - Work products contain the verification of the quality assurance + * - 4 + - Only quality-assured project/platform releases are delivered to the community + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - 100% of project/platform releases delivered to the community are quality-assured + - Feature is released as experimental + - Ensured by the process release management, :need:`PROCESS_wp__platform_sw_release_note` contain the verification and approval of the quality-assurance + * - 5 + - Only quality-trained personnel are part of the :need:`PROCESS_rl__committer` + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - 100% of personnel are trained + - None + - Ensured by the process platform management, :need:`PROCESS_wp__training_path` contain the training material and evidences for conducted trainings + * - 6 + - No overdue quality assurance closure activities + - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` + - 100% of the quality improvement, non-conformance issues are closed + - None + - Ensured by the process quality management, :need:`PROCESS_wp__issue_track_system` contain improvments and non-coformancees + + +3.4 Work Product Quality Goals +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: Work Product Quality Goals + :header-rows: 1 + + * - # + - **Work Product** + - **Quality Criteria** + - **Target value** + - **Allowed variation** + - **Metric** + * - 1 + - :need:`PROCESS_wp__feat_request` + - | Feature request is reviewed and accepted + - 100% + - None + - Ensured by process livecycle concept, evidences for participants available, feedback of participants documented + * - 2 + - :doc:`../requirements/stakeholder/index` + - | All stakeholder requirements are reviewed and valid + | All stakeholder requirements are at least satisfied by one feature requirement + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 3 + - <wp__tool_verification_report> + - | All tool requirements are reviewed and valid + | All tool requirements have bidirectional traceability to and from process requirements or guidance + - 100% + - None + - Ensured by process configuration and tool management, only verified and valid documents can be merged, review required + * - 4 + - :need:`PROCESS_wp__requirements__feat` + - | All feature requirements are reviewed and valid + | All feature requirements have bidirectional traceability to and from stakeholder requirements + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 5 + - :need:`PROCESS_wp__requirements__comp` + - | All component requirements are reviewed and valid + | All component requirements have bidirectional traceability to and from feature requirements + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 6 + - :need:`PROCESS_wp__requirements__feat_aou` + - | All feature aou are reviewed and valid + | All feature aou have bidirectional traceability to and from feature requirements + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 7 + - :need:`PROCESS_wp__requirements__comp_aou` + - | All component aou are reviewed and valid + | All component aou have bidirectional traceability to and from feature requirements + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 8 + - :need:`PROCESS_wp__hsi` + - | Hardware and Software interaction is specified and consistent with the technical safety concept + | All component HW parts that are controlled by the software are included + | All HW resources that support the SW execution are included + - 100% + - None + - Ensured by quality management, only verified and valid documents can be merged, review required + * - 9 + - :need:`PROCESS_wp__requirements__inspect` + - | All requirements were inspected by review with inspection checklist. + - 100% + - None + - Ensured by process configuration and tool management, only verified and valid documents can be merged, review required + * - 10 + - :need:`PROCESS_wp__feature_arch` + - | All feature architectures are reviewed and valid + | All feature architectures have bidirectional traceability to and from feature requirements + - 100% + - None + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check + * - 11 + - :need:`PROCESS_wp__feature_safety_analysis` + - | Inductive (bottom-up) safety analysis e.g. FMEA is completed. Analysis verifies the feature architecture. + | All detection and prevention mitigations are linked to Software Feature Requirements or Assumptions of use. + - 100% + - None + - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check + * - 12 + - :need:`PROCESS_wp__component_arch` + - | All component architectures are reviewed and valid + | All component architectures have bidirectional traceability to and from components requirements or feature architectures + - 100% + - None + - Ensured by process configuration and tool management, only valid architecture can be merged, review required, script based check + * - 13 + - :need:`PROCESS_wp__sw_component_safety_analysis` + - | Inductive (bottom-up) safety analysis e.g. FMEA is completed. Analysis verifies the component architecture. + | All detection and prevention mitigations are linked to Software Component Requirements or Assumptions of use. + - 100% + - None + - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check + * - 14 + - :need:`PROCESS_wp__sw_arch_verification` + - | Architecture verification is available and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid architecture can be merged, review required, script based check + * - 15 + - :need:`PROCESS_wp__sw_implementation` + - | Implementation of source code has been done after creation of detailed design. + | SW configuration is described. + - 100% + - None + - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check + * - 16 + - :need:`PROCESS_wp__verification__sw_unit_test` + - | Detailed design is verified by unit testing. + - 100% + - None + - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check + * - 17 + - :need:`PROCESS_wp__sw_implementation_inspection` + - | Inspection is done by inspection checklist. + - 100% + - None + - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check + * - 18 + - :need:`PROCESS_wp__verification__feat_int_test` + - | All interfaces from static view and all flows from dynamic view are valid and reviewed. + | Performance expectations (RAM, processor usage, ..) on reference hardware are described. + - 100% + - None + - Ensured by process configuration and tool management, only valid features can be merged, verification required, script based check + * - 19 + - :need:`PROCESS_wp__verification__comp_int_test` + - | All interfaces from static view and all flows from dynamic view are valid and reviewed. + | Integration of units into components is based on the detailed design. + - 100% + - None + - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check + * - 20 + - :need:`PROCESS_wp__verification__module_ver_report` + - | Module verification report is available and valid for every module. + - 100% + - None + - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check + * - 21 + - :need:`PROCESS_wp__sw_component_class` + - | Software component classification is available and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check + * - 22 + - :need:`PROCESS_wp__training_path` + - | All training material is available and valid, training planned and executed + | All training paths has been scheduled and executed + - 100% + - None + - Ensured by process platform management, evidences for participants available, feedback of participants documented + * - 23 + - :need:`PROCESS_wp__issue_track_system` + - All issues follow the planning strategy defined in the project/platform management plan + - 100% + - None + - Ensured by project management and tool management, only issues following the strategy can be part of any PR + * - 24 + - :need:`PROCESS_wp__platform_mgmt` + - All findings from work product review are resolved anf reviewed. Document is valid. + - 100% + - None + - Ensured by project management, only verified and valid documents can be merged, review required + * - 25 + - :need:`PROCESS_wp__process_definition` + - All findings from platform audit are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by process management and tool management, only verified and valid documents can be merged, review required + * - 26 + - :need:`PROCESS_wp__process_impr_report` + - Process improvement report is available and valid for every platform release. + - 100% + - None + - Ensured by quality management and tool management, only verified and valid documents can be merged, review required + * - 27 + - :need:`PROCESS_wp__process_plan` + - The process strategy is defined, available and valid. + - 100% + - None + - Ensured by process management and tool management, only verified and valid documents can be merged, review required + * - 28 + - :need:`PROCESS_wp__module_safety_plan` + - All findings from work product review are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 29 + - :need:`PROCESS_wp__module_safety_package` + - All findings from work product review are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 30 + - :need:`PROCESS_wp__platform_safety_plan` + - All findings from work product review are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 31 + - :need:`PROCESS_wp__platform_safety_package` + - All findings from work product review are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 32 + - :need:`PROCESS_wp__fdr_reports` + - CMR reports (Safety Plan, Safety Case, Safety Analyses and DFA) are available and valid for every platform release. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 33 + - :need:`PROCESS_wp__audit_report` + - Process Safety Audit report is available and valid for every platform release. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 34 + - :need:`PROCESS_wp__feature_dfa` + - | DFA on platform/feature level is available and valid. + | All detection and prevention mitigations linked to Software Feature Requirements or Assumptions of Use. + - 100% + - None + - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check + * - 35 + - :need:`PROCESS_wp__sw_component_dfa` + - | DFA on component/module level is available and valid. + | All detection and prevention mitigations linded to Software Component Requirements or Assumptions of Use. + - 100% + - None + - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check + * - 36 + - :need:`PROCESS_wp__module_sw_build_config` + - | Build configuration is capable to create the SEooC Library on the reference HW, module level. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 37 + - :need:`PROCESS_wp__module_safety_manual` + - | Safety Manual for every module is available, up to date and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 38 + - :need:`PROCESS_wp__module_sw_release_note` + - | All known bugs are described with a clear statement that these bugs do not lead to violation of any safety requirements or corresponding workaround measures. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 39 + - :need:`PROCESS_wp__sw_development_plan` + - | SW Development Plan is available, up to date and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 40 + - :need:`PROCESS_wp__verification__plan` + - | Verification Plan is available, up to date and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 41 + - :need:`PROCESS_wp__tool_verification_report` + - | All tool conficence levels (TCL) are determined. Appropriate qualification methods are applied. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 42 + - :need:`PROCESS_wp__tailoring` + - | Argumentation for all tailored (not needed) work products in the project is available and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 43 + - :need: wp__qms_plan + - | Quality Management Plan is available, up to date and valid + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + +3.5 Quality Management Scope +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +There is no deviation from the scope defined in the :need:`doc__project_mgt_plan`. The platform and its +components are developed, and integrated for an assumed technical system, for functional safety purposes as +Safety Element out of Context (SEooC). + +The development of the platform and its components follows the defined processes. Responsibilities for management, +development, implementation, integration and verification are also defined in the processes. + +The SW platform consists of features, which are based on a set of requirements and are developed in parallel. + +**Tailoring of quality assurance activities** + +* The tailoring is divided into project wide and feature specific rules. +* Project wide tailoring is documented in <link to aspice> - this is based on the development of a SW element + +3.6 Quality Management Organization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +It is the project strategy to qualify the platform or components of the platform to the appropriate international +standards and directives. Therefore the project approach to facilitate a common culture regarding quality, safety +and security is part of our documentation. The project will be under the Eclipse Foundation and so the +`Eclipse Foundation Project Handbook <https://www.eclipse.org/projects/handbook/>`_ applies. + +**Project Roles** + +The role of the :need:`PROCESS_rl__quality_manager` is defined. + +**Critical dependencies** + +The project has not implemented a quality management system yet. But it aims to be conformant to ASPICE 4.0, +as defined in the management system. Continuous improvement is part of all processes. Improvements are handled +in the scope of Quality Management. + +**Risk** + +Organization and management system is currently not mature. + +**Skills** + +The main quality related project roles are the project manager and the quality manager and these also have to have +the (Eclipse) committer role. As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the +committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the +project processes in several previous pull requests. + +As each project can adopt additional criteria for the committers election, we define that each committer has to prove +his knowledge in quality SW development by: + +- by attending the project's ASPICE 4.0 SW management and development training (given by a project lead, quality manager or safety team member) + +Additionally the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull +request modifying a file in their area before it is merged. In case of quality related "CODEOWNER" sections (e.g. +any documentation artefacts) the persons having "CODEOWNER" rights need to have: + +- At least one year of professional practice of quality related SW development (or management) relevant for the section content with demonstrable and verifiable results. + +The successful checking of committers and CODEOWNERS skills is ensured by the project and quality manager and documented +in the role assignment document. + +.. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the quality manager role for the approvals + +4 Quality Management Planning +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +4.1 Quality Resources +"""""""""""""""""""""" +A dedicated Quality Manager is defined as part of the cross functional teams as defined in :doc:`project_management`. The Quality Manager, supported by the +Project Manager, and all other stakeholders, will ensure that quality activities are actively planned, developed, +analyzed, verified and tested and managed throughout the life cycle of the project. As all the implementation +takes place within feature development, there is a quality manager appointed in the feature development plan. + +Resources and milestones are planned in Github Issues for all activities. There are issue templates for sagas +(covering one feature development) and for epics (covering one development workproduct each). Resource and +milestone planning is done as defined in the :doc:`project_management`. + +**Tools** + +The whole development and thus all work products are located in Github. The development is automated as much as +possible and follows the defined processes. + +- Github issues are used for planning. +- The issue types and issue types workflows are described in the platform management plan. +- For quality relevant issue types a ``quality`` label is used. + +4.2 Quality Management Communication +"""""""""""""""""""""""""""""""""""" +To exchange general information and to clarify general topics, the following communication channels are used: +- Regular (online) meetings +- E-Mails +- Messager Services e.g., Slack, Microsoft Teams, Github Notifications + +Ad-hoc quality related meetings are set up for clarification topics. + +**Reporting** + +The quality management status is reported as defined in the platform management plan. The status report includes +at least the defined Quality Criteria defined in this document. + +**Escalation** + +- Quality Manager to Steering Council + +**Examples for valid escalation causes are:** + +- Quality issues cannot be resolved on feature level or with the available resources. +- There are conflicting points of view between the Project Manager, Safety Manager and the Quality Manager + +4.3 Quality Management Specifics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +None + +4.4 Quality Management Generic workproducts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: Quality related work products + :header-rows: 1 + + * - Workproduct Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - wp__audit_report + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - + - :need:`PROCESS_wp__audit_report` + - valid + + * - wp__chm_plan + - :need:`PROCESS_gd_guidl__change__change_request` + - valid + - + - :need:`PROCESS_wp__chm_plan` + - valid + + * - wp__cmpt_request + - :need:`PROCESS_gd_guidl__change__change_request` + - valid + - + - :need:`PROCESS_wp__cmpt_request` + - valid + + * - wp__component_arch + - :need:`PROCESS_gd_guidl__arch__design` + - valid + - + - :need:`PROCESS_wp__component_arch` + - valid + + * - wp__document_mgt_plan + - :need:`PROCESS_gd_guidl__documentation` + - valid + - n/a + - :need:`PROCESS_wp__document_mgt_plan` + - valid + + * - wp__fdr_reports + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__fdr_reports` + - valid + + * - wp__feat_request + - :need:`PROCESS_gd_guidl__change__change_request` + - valid + - + - :need:`PROCESS_wp__feat_request` + - valid + + * - wp__feature_arch + - :need:`PROCESS_gd_guidl__arch__design` + - valid + - + - :need:`PROCESS_wp__feature_arch` + - valid + + * - wp__feature_dfa + - + - valid + - n/a + - :need:`PROCESS_wp__feature_dfa` + - valid + + * - wp__feature_safety_analysis + - + - valid + - n/a + - :need:`PROCESS_wp__feature_safety_analysis` + - valid + + * - wp__hsi + - n/a + - valid + - n/a + - :need:`PROCESS_wp__hsi` + - valid + + * - wp__issue_track_system + - :need:`PROCESS_gd_guidl__change__change_request` + - valid + - + - :need:`PROCESS_wp__issue_track_system` + - valid + + * - wp__module_safety_manual + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__module_safety_manual` + - valid + + * - wp__module_safety_package + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__module_safety_package` + - valid + + * - wp__module_safety_plan + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__module_safety_plan` + - valid + + * - wp__platform_sw_build_config + - + - + - n/a + - :need:`PROCESS_wp__platform_sw_build_config` + - draft + + * - wp__platform_sw_release_note + - + - + - n/a + - :need:`PROCESS_wp__platform_sw_release_note` + - valid + + * - wp__policies + - + - + - n/a + - :need:`PROCESS_wp__policies` + - draft + + * - wp__prm_plan + - :need:`PROCESS_gd_guidl__problem__problem` + - valid + - n/a + - :need:`PROCESS_wp__prm_plan` + - valid + + * - valid + - + - + - n/a + - :need:`PROCESS_wp__process_definition` + - draft + + * - wp__process_impr_report + - :need: gd_guidl__qlm_plan_definitions + - valid + - n/a + - :need: wp__process_impr_report + - valid + + * - wp__process_plan + - + - valid + - n/a + - :need:`PROCESS_wp__process_plan` + - valid + + * - wp__project_mgt + - + - valid + - n/a + - :need:`PROCESS_wp__project_mgt` + - valid + + * - wp__qms_plan + - :need: gd_guidl__qlm_plan_definitions + - valid + - n/a + - :need: wp__qms_plan + - valid + + * - wp__qms_report + - :need: gd_guidl__qlm_plan_definitions + - valid + - n/a + - :need: wp__qms_report + - valid + + * - wp__requirements__comp + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__comp` + - valid + + * - wp__requirements__comp_aou + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__comp_aou` + - valid + + * - wp__requirements__feat + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__feat` + - valid + + * - wp__requirements__feat_aou + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__feat_aou` + - valid + + * - wp__requirements__inspect + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__inspect` + - valid + + * - wp__requirements__stkh + - :need:`PROCESS_gd_guidl__req__engineering` + - valid + - n/a + - :need:`PROCESS_wp__requirements__stkh` + - valid + + * - wp__sw_arch_verification + - :need:`PROCESS_gd_guidl__arch__design` + - valid + - n/a + - :need:`PROCESS_wp__sw_arch_verification` + - valid + + * - wp__sw_component_class + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__sw_component_class` + - valid + + * - wp__sw_component_dfa + - + - valid + - n/a + - :need:`PROCESS_wp__sw_component_dfa` + - valid + + * - wp__sw_component_safety_analysis + - + - valid + - n/a + - :need:`PROCESS_wp__sw_component_safety_analysis` + - valid + + * - wp__sw_development_plan + - :need:`PROCESS_gd_guidl__implementation` + - valid + - n/a + - :need:`PROCESS_wp__sw_development_plan` + - valid + + * - wp__sw_implementation + - :need:`PROCESS_gd_guidl__implementation` + - valid + - n/a + - :need:`PROCESS_wp__sw_implementation` + - valid + + * - wp__sw_implementation_inspection + - :need:`PROCESS_gd_guidl__implementation` + - valid + - n/a + - :need:`PROCESS_wp__sw_implementation_inspection` + - valid + + * - wp__tailoring + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__tailoring` + - valid + + * - wp__tailoring_platform + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - valid + - n/a + - :need:`PROCESS_wp__tailoring` + - valid + + * - wp__tool_verification + - + - + - n/a + - :need:`PROCESS_wp__tool_verification_report` + - valid + + * - wp__training_path + - + - + - n/a + - :need:`PROCESS_wp__training_path` + - draft + + * - wp__verification__comp_int_test + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__comp_int_test` + - valid + + * - wp__verification__feat_int_test + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__feat_int_test` + - valid + + * - wp__verification__module_ver_report + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__module_ver_report` + - valid + + * - wp__verification__plan + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__plan` + - valid + + * - wp__verification__platform_test + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__platform_test` + - valid + + * - wp__verification__platform_ver_report + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__platform_ver_report` + - valid -Approach -++++++++ + * - wp__verification__sw_unit_test + - :need:`PROCESS_gd_guidl__verification_guide` + - valid + - n/a + - :need:`PROCESS_wp__verification__sw_unit_test` + - valid \ No newline at end of file diff --git a/docs/platform_management_plan/requirements_management.rst b/docs/platform_management_plan/requirements_management.rst deleted file mode 100644 index e2a6b5a402..0000000000 --- a/docs/platform_management_plan/requirements_management.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -Requirements management ------------------------- - -Purpose -+++++++ - -Objectives and scope -++++++++++++++++++++ - -Approach -++++++++ diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index b915c3ed6a..4b3c12318d 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -251,7 +251,7 @@ is determined by Safety Audit and not be Eclipse project reviews. Functional Safety Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Requirement Engineering is defined in the process description. See :doc:`requirements_management`. +Requirement Engineering is defined in the process description. See :need:`PROCESS_doc_concept__req__process`. The application of ISO 26262 standards requirements is realized by defining process guidances and matching those to the ISO 26262 requirements (see e.g. for example :need:`PROCESS_gd_req__sm_doc_status`). From e5b0132445c6bdb5d61525444575f2fe6c69800b Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Thu, 12 Jun 2025 14:40:32 +0200 Subject: [PATCH 042/102] process: include review findings Ref: closes #1211 --- .../quality_management.rst | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index c207847c31..22f8a69498 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -19,7 +19,7 @@ Quality Management / Platform Quality Management Plan :id: doc__platform_quality_plan :status: valid :safety: ASIL_B - :realizes: wp__qms_plan + :realizes: PROCESS_wp__qms_plan :tags: platform_management Purpose @@ -36,18 +36,18 @@ of the workflows. Statement of Independence ------------------------- -There could be a conflict of interest between the project lead :need:`PROCESS_rl__project_lead` and the quality manager -:need:`PROCESS_rl__quality_manager`, as both roles are responsible for the project. The project lead is responsible for -the project and the quality manager is responsible for the quality of the project. +There could be a conflict of interest between the project lead :need:`PROCESS_rl__project_lead` and the quality manager +:need:`PROCESS_rl__quality_manager`, as both roles are responsible for the project. The project lead :need:`PROCESS_rl__project_lead` is responsible for +the project and the quality manager :need:`PROCESS_rl__quality_manager` is responsible for the quality of the project. -Therefore we define that the quality manager only support the project with consulting. So the project itself -shall improve the quality of the project/platform product. The combination of both shall found the best solution +Therefore we define that the quality manager :need:`PROCESS_rl__quality_manager` only support the project with consulting. So the project itself +shall improve the quality of the project/platform product. The combination of both shall found the best solution for the project. The quality report is sent to the :need:`PROCESS_rl__technical_lead` so that conflicts can be solved -in the steering committees. +in the steering committees :need:`doc__project_mgt_plan`. The objectives and scope of the quality management, also the measures and checklists are transparent for everyone. So the project itself can improve the quality of the project/platform product with the support of the knowledge of -the quality manager. +the quality manager :need:`PROCESS_rl__quality_manager`. Objectives and scope -------------------- @@ -483,7 +483,7 @@ Organization and management system is currently not mature. **Skills** -The main quality related project roles are the project manager and the quality manager and these also have to have +The main quality related project roles are the project lead :need:`PROCESS_rl__project_lead` and the quality manager :need:`PROCESS_rl__quality_manager` and these also have to have the (Eclipse) committer role. As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. @@ -491,7 +491,7 @@ project processes in several previous pull requests. As each project can adopt additional criteria for the committers election, we define that each committer has to prove his knowledge in quality SW development by: -- by attending the project's ASPICE 4.0 SW management and development training (given by a project lead, quality manager or safety team member) +- by attending the project's ASPICE 4.0 SW management and development training Additionally the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull request modifying a file in their area before it is merged. In case of quality related "CODEOWNER" sections (e.g. @@ -499,19 +499,19 @@ any documentation artefacts) the persons having "CODEOWNER" rights need to have: - At least one year of professional practice of quality related SW development (or management) relevant for the section content with demonstrable and verifiable results. -The successful checking of committers and CODEOWNERS skills is ensured by the project and quality manager and documented +The successful checking of committers and CODEOWNERS skills is ensured by the project lead :need:`PROCESS_rl__project_lead` and quality manager :need:`PROCESS_rl__quality_manager` and documented in the role assignment document. -.. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the quality manager role for the approvals +.. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the quality manager :need:`PROCESS_rl__quality_manager` role for the approvals 4 Quality Management Planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4.1 Quality Resources """""""""""""""""""""" -A dedicated Quality Manager is defined as part of the cross functional teams as defined in :doc:`project_management`. The Quality Manager, supported by the -Project Manager, and all other stakeholders, will ensure that quality activities are actively planned, developed, +A dedicated Quality Manager :need:`PROCESS_rl__quality_manager` is defined as part of the cross functional feature teams as defined in :doc:`project_management`. The Quality Manager :need:`PROCESS_rl__quality_manager`, supported by the +Project Lead :need:`PROCESS_rl__project_lead`, and all other stakeholders, will ensure that quality activities are actively planned, developed, analyzed, verified and tested and managed throughout the life cycle of the project. As all the implementation -takes place within feature development, there is a quality manager appointed in the feature development plan. +takes place within feature development, there is a quality manager :need:`PROCESS_rl__quality_manager` appointed in the feature development plan. Resources and milestones are planned in Github Issues for all activities. There are issue templates for sagas (covering one feature development) and for epics (covering one development workproduct each). Resource and @@ -538,16 +538,16 @@ Ad-hoc quality related meetings are set up for clarification topics. **Reporting** The quality management status is reported as defined in the platform management plan. The status report includes -at least the defined Quality Criteria defined in this document. +at least the defined Quality Criteria defined in this document :need:`PROCESS_wp__qms_report`. **Escalation** -- Quality Manager to Steering Council +- Quality Manager :need:`PROCESS_rl__quality_manager` to steering committees :need:`doc__project_mgt_plan`. **Examples for valid escalation causes are:** - Quality issues cannot be resolved on feature level or with the available resources. -- There are conflicting points of view between the Project Manager, Safety Manager and the Quality Manager +- There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Safety Manager :need:`PROCESS_rl__safety_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` 4.3 Quality Management Specifics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -907,4 +907,4 @@ None - valid - n/a - :need:`PROCESS_wp__verification__sw_unit_test` - - valid \ No newline at end of file + - valid From 835228a07f27025e532ee582f5ce85745c9bcfdb Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Mon, 16 Jun 2025 12:36:04 +0200 Subject: [PATCH 043/102] process: update links to process repo Ref: closes #1211 --- docs/platform_management_plan/quality_management.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index 22f8a69498..cb70d08324 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -130,15 +130,15 @@ Objectives and scope - Feature is released as experimental - Ensured by the process quality and tool management, :need:`PROCESS_wp__qms_report` - Process conformance is available * - 3 - - Only quality-assured project/platform work products are delivered to the community + - Only quality-assured project/platform work products are formaly delivered to the community - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - 100% of project/platform work products are quality-assured - Feature is released as experimental - Ensured by the process quality and tool management, :need:`PROCESS_wp__verification__platform_ver_report` - Work products contain the verification of the quality assurance * - 4 - - Only quality-assured project/platform releases are delivered to the community + - Only quality-assured project/platform releases are dformaly elivered to the community - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - - 100% of project/platform releases delivered to the community are quality-assured + - 100% of project/platform releases formaly delivered to the community are quality-assured - Feature is released as experimental - Ensured by the process release management, :need:`PROCESS_wp__platform_sw_release_note` contain the verification and approval of the quality-assurance * - 5 From d6f9d0fc99f07caa7fc45dc61cb7e683cadd419e Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Mon, 16 Jun 2025 20:04:52 +0200 Subject: [PATCH 044/102] process: continue review Ref: closes #1211 --- .../quality_management.rst | 725 ++++++++++-------- 1 file changed, 398 insertions(+), 327 deletions(-) diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index cb70d08324..017fddf14b 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -25,29 +25,20 @@ Quality Management / Platform Quality Management Plan Purpose ------- -The purpose of this document is to is to define a quality strategy and an approach for the platform. +The purpose of this document is to define a quality strategy and an approach for the platform. This includes an approach to providing an independent and objective assurance that work products and processes comply with predefined provisions and plans and that non-conformances are resolved and further prevented. This document includes quality assurance activities, roles and responsibilities, goals, schedule, etc. and a -general strategy to implement a quality assurance process in this platform. The quality assurance is +general strategy to implement quality assurance process in this platform. The quality assurance is ensured by automated checks and restrictions, manual checks which inculdes to proof that there is no manipulation of the workflows. Statement of Independence ------------------------- -There could be a conflict of interest between the project lead :need:`PROCESS_rl__project_lead` and the quality manager -:need:`PROCESS_rl__quality_manager`, as both roles are responsible for the project. The project lead :need:`PROCESS_rl__project_lead` is responsible for -the project and the quality manager :need:`PROCESS_rl__quality_manager` is responsible for the quality of the project. - -Therefore we define that the quality manager :need:`PROCESS_rl__quality_manager` only support the project with consulting. So the project itself -shall improve the quality of the project/platform product. The combination of both shall found the best solution -for the project. The quality report is sent to the :need:`PROCESS_rl__technical_lead` so that conflicts can be solved -in the steering committees :need:`doc__project_mgt_plan`. - -The objectives and scope of the quality management, also the measures and checklists are transparent for everyone. -So the project itself can improve the quality of the project/platform product with the support of the knowledge of -the quality manager :need:`PROCESS_rl__quality_manager`. +The :need:`PROCESS_rl__quality_manager` provides only support to the project with consulting them to improve the +quality of the project/platform product. Although the quality report is also sent to the :need:`PROCESS_rl__technical_lead`, +the :need:`PROCESS_rl__quality_manager` is independent of the delivery of the product. Objectives and scope -------------------- @@ -89,7 +80,7 @@ Objectives and scope - Platform Process audit - Once for every platform release or on demand * - 2 - - Feature Process compliance checks + - Feature Process conformance checks - Once for every feature release * - 3 - Feature Work product review @@ -130,21 +121,21 @@ Objectives and scope - Feature is released as experimental - Ensured by the process quality and tool management, :need:`PROCESS_wp__qms_report` - Process conformance is available * - 3 - - Only quality-assured project/platform work products are formaly delivered to the community + - Only quality-assured project/platform work products are delivered to the community - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - 100% of project/platform work products are quality-assured - Feature is released as experimental - Ensured by the process quality and tool management, :need:`PROCESS_wp__verification__platform_ver_report` - Work products contain the verification of the quality assurance * - 4 - - Only quality-assured project/platform releases are dformaly elivered to the community + - Only quality-assured project/platform releases are delivered to the community - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - - 100% of project/platform releases formaly delivered to the community are quality-assured + - 100% of project/platform releases delivered to the community are quality-assured - Feature is released as experimental - Ensured by the process release management, :need:`PROCESS_wp__platform_sw_release_note` contain the verification and approval of the quality-assurance * - 5 - Only quality-trained personnel are part of the :need:`PROCESS_rl__committer` - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - - 100% of personnel are trained + - 100% of personnel are trained as per committer role description in :need:`PROCESS_rl__committer` - None - Ensured by the process platform management, :need:`PROCESS_wp__training_path` contain the training material and evidences for conducted trainings * - 6 @@ -172,7 +163,7 @@ Objectives and scope - | Feature request is reviewed and accepted - 100% - None - - Ensured by process livecycle concept, evidences for participants available, feedback of participants documented + - Ensured by the process quality management, :need:`PROCESS_wp__issue_track_system` contain improvements and non-coformances with a set due date * - 2 - :doc:`../requirements/stakeholder/index` - | All stakeholder requirements are reviewed and valid @@ -181,12 +172,12 @@ Objectives and scope - None - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check * - 3 - - <wp__tool_verification_report> + - :need:`PROCESS_wp__tool_verification_report` - | All tool requirements are reviewed and valid | All tool requirements have bidirectional traceability to and from process requirements or guidance - 100% - None - - Ensured by process configuration and tool management, only verified and valid documents can be merged, review required + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check * - 4 - :need:`PROCESS_wp__requirements__feat` - | All feature requirements are reviewed and valid @@ -228,7 +219,7 @@ Objectives and scope - | All requirements were inspected by review with inspection checklist. - 100% - None - - Ensured by process configuration and tool management, only verified and valid documents can be merged, review required + - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check * - 10 - :need:`PROCESS_wp__feature_arch` - | All feature architectures are reviewed and valid @@ -311,7 +302,7 @@ Objectives and scope * - 22 - :need:`PROCESS_wp__training_path` - | All training material is available and valid, training planned and executed - | All training paths has been scheduled and executed + | All training paths have been scheduled and executed - 100% - None - Ensured by process platform management, evidences for participants available, feedback of participants documented @@ -358,87 +349,106 @@ Objectives and scope - None - Ensured by safety management, only verified and valid documents can be merged, review required * - 30 - - :need:`PROCESS_wp__platform_safety_plan` + - :need:`PROCESS_wp__module_safety_package` - All findings from work product review are resolved and reviewed. Document is valid. - 100% - None - Ensured by safety management, only verified and valid documents can be merged, review required * - 31 - - :need:`PROCESS_wp__platform_safety_package` + - :need:`PROCESS_wp__platform_safety_plan` - All findings from work product review are resolved and reviewed. Document is valid. - 100% - None - Ensured by safety management, only verified and valid documents can be merged, review required * - 32 + - :need:`PROCESS_wp__platform_safety_package` + - All findings from work product review are resolved and reviewed. Document is valid. + - 100% + - None + - Ensured by safety management, only verified and valid documents can be merged, review required + * - 33 - :need:`PROCESS_wp__fdr_reports` - CMR reports (Safety Plan, Safety Case, Safety Analyses and DFA) are available and valid for every platform release. - 100% - None - Ensured by safety management, only verified and valid documents can be merged, review required - * - 33 + * - 34 - :need:`PROCESS_wp__audit_report` - Process Safety Audit report is available and valid for every platform release. - 100% - None - Ensured by safety management, only verified and valid documents can be merged, review required - * - 34 + * - 35 + - :need:`PROCESS_wp__platform_feature_dfa` + - | DFA on platform feature level is available and valid. + | All detection and prevention mitigations linked to Software Feature Requirements or Assumptions of Use. + - 100% + - None + - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check + * - 36 - :need:`PROCESS_wp__feature_dfa` - - | DFA on platform/feature level is available and valid. + - | DFA on feature level is available and valid. | All detection and prevention mitigations linked to Software Feature Requirements or Assumptions of Use. - 100% - None - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 35 + * - 37 - :need:`PROCESS_wp__sw_component_dfa` - | DFA on component/module level is available and valid. | All detection and prevention mitigations linded to Software Component Requirements or Assumptions of Use. - 100% - None - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 36 + * - 38 - :need:`PROCESS_wp__module_sw_build_config` - | Build configuration is capable to create the SEooC Library on the reference HW, module level. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 37 + * - 39 - :need:`PROCESS_wp__module_safety_manual` - | Safety Manual for every module is available, up to date and valid. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 38 + * - 40 - :need:`PROCESS_wp__module_sw_release_note` - | All known bugs are described with a clear statement that these bugs do not lead to violation of any safety requirements or corresponding workaround measures. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 39 + * - 41 - :need:`PROCESS_wp__sw_development_plan` - | SW Development Plan is available, up to date and valid. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 40 + * - 42 - :need:`PROCESS_wp__verification__plan` - | Verification Plan is available, up to date and valid. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 41 + * - 43 + - :need:`PROCESS_wp__tlm_plan` + - | Tool Management Plan is available, up to date and valid. + - 100% + - None + - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check + * - 44 - :need:`PROCESS_wp__tool_verification_report` - | All tool conficence levels (TCL) are determined. Appropriate qualification methods are applied. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 42 + * - 45 - :need:`PROCESS_wp__tailoring` - | Argumentation for all tailored (not needed) work products in the project is available and valid. - 100% - None - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 43 - - :need: wp__qms_plan + * - 46 + - :need:`PROCESS_wp__qms_plan` - | Quality Management Plan is available, up to date and valid - 100% - None @@ -451,29 +461,41 @@ components are developed, and integrated for an assumed technical system, for fu Safety Element out of Context (SEooC). The development of the platform and its components follows the defined processes. Responsibilities for management, -development, implementation, integration and verification are also defined in the processes. +development, implementation, integration, and verification are also defined in the processes. The SW platform consists of features, which are based on a set of requirements and are developed in parallel. **Tailoring of quality assurance activities** * The tailoring is divided into project wide and feature specific rules. -* Project wide tailoring is documented in <link to aspice> - this is based on the development of a SW element +* Project wide tailoring is documented in `ASPICE 4.0 <https://eclipse-score.github.io/process_description/main/standards/aspice_40/aspice.html>`_ - this is based on the development of a SW element. 3.6 Quality Management Organization ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ It is the project strategy to qualify the platform or components of the platform to the appropriate international standards and directives. Therefore the project approach to facilitate a common culture regarding quality, safety -and security is part of our documentation. The project will be under the Eclipse Foundation and so the +and security is part of the documentation. The project is stewarded by the Eclipse Foundation and so the `Eclipse Foundation Project Handbook <https://www.eclipse.org/projects/handbook/>`_ applies. **Project Roles** -The role of the :need:`PROCESS_rl__quality_manager` is defined. +The project roles are defined in the processes and are aligned to Eclipse roles. + +.. needtable:: + :style: table + :columns: title;id;tags + :colwidths: 25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["role"]): + results.append(need) + -**Critical dependencies** +| **Critical dependencies** -The project has not implemented a quality management system yet. But it aims to be conformant to ASPICE 4.0, +The project has not implemented a quality management system yet, but aims to be conformant to ASPICE 4.0, as defined in the management system. Continuous improvement is part of all processes. Improvements are handled in the scope of Quality Management. @@ -483,35 +505,35 @@ Organization and management system is currently not mature. **Skills** -The main quality related project roles are the project lead :need:`PROCESS_rl__project_lead` and the quality manager :need:`PROCESS_rl__quality_manager` and these also have to have +The main quality related project roles are the Project Lead :need:`PROCESS_rl__project_lead` and the Quality Manager :need:`PROCESS_rl__quality_manager` and these also have to have the (Eclipse) committer role. As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. -As each project can adopt additional criteria for the committers election, we define that each committer has to prove +As each project can adopt additional criteria for the committers election, S-Core defines that each committer has to prove his knowledge in quality SW development by: -- by attending the project's ASPICE 4.0 SW management and development training +- by attending the project's ASPICE 4.0 SW management and development training. -Additionally the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull -request modifying a file in their area before it is merged. In case of quality related "CODEOWNER" sections (e.g. +Additionally, the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull +request modifying a file in their area of responsibility before it gets merged. In case of quality related "CODEOWNER" sections (e.g. any documentation artefacts) the persons having "CODEOWNER" rights need to have: - At least one year of professional practice of quality related SW development (or management) relevant for the section content with demonstrable and verifiable results. -The successful checking of committers and CODEOWNERS skills is ensured by the project lead :need:`PROCESS_rl__project_lead` and quality manager :need:`PROCESS_rl__quality_manager` and documented +The successful checking of committers and CODEOWNERS skills is ensured by the project and Quality Manager :need:`PROCESS_rl__quality_manager` and documented in the role assignment document. -.. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the quality manager :need:`PROCESS_rl__quality_manager` role for the approvals +.. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the Quality Manager :need:`PROCESS_rl__quality_manager` role for the approvals 4 Quality Management Planning ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4.1 Quality Resources """""""""""""""""""""" -A dedicated Quality Manager :need:`PROCESS_rl__quality_manager` is defined as part of the cross functional feature teams as defined in :doc:`project_management`. The Quality Manager :need:`PROCESS_rl__quality_manager`, supported by the +A dedicated Quality Manager is defined as part of the cross functional feature teams as defined in :doc:`project_management`. The Quality Manager :need:`PROCESS_rl__quality_manager`, supported by the Project Lead :need:`PROCESS_rl__project_lead`, and all other stakeholders, will ensure that quality activities are actively planned, developed, -analyzed, verified and tested and managed throughout the life cycle of the project. As all the implementation -takes place within feature development, there is a quality manager :need:`PROCESS_rl__quality_manager` appointed in the feature development plan. +analyzed, verified, tested, and managed throughout the life cycle of the project. As all the implementation +takes place within feature development, there is a Quality Manager :need:`PROCESS_rl__quality_manager` appointed in the feature development plan. Resources and milestones are planned in Github Issues for all activities. There are issue templates for sagas (covering one feature development) and for epics (covering one development workproduct each). Resource and @@ -523,8 +545,8 @@ The whole development and thus all work products are located in Github. The deve possible and follows the defined processes. - Github issues are used for planning. -- The issue types and issue types workflows are described in the platform management plan. -- For quality relevant issue types a ``quality`` label is used. +- The issue types and their workflows are described in the platform management plan. +- For quality relevant issue types the ``quality`` label is used. 4.2 Quality Management Communication """""""""""""""""""""""""""""""""""" @@ -538,16 +560,16 @@ Ad-hoc quality related meetings are set up for clarification topics. **Reporting** The quality management status is reported as defined in the platform management plan. The status report includes -at least the defined Quality Criteria defined in this document :need:`PROCESS_wp__qms_report`. +at least the defined Quality Criteria defined in this document. **Escalation** -- Quality Manager :need:`PROCESS_rl__quality_manager` to steering committees :need:`doc__project_mgt_plan`. +- Quality Manager :need:`PROCESS_rl__quality_manager` to steering committee documented in :need:`doc__project_mgt_plan`. **Examples for valid escalation causes are:** - Quality issues cannot be resolved on feature level or with the available resources. -- There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Safety Manager :need:`PROCESS_rl__safety_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` +- There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Safety Manager :need:`PROCESS_rl__safety_manager`, Security Manager :need:`PROCESS_rl__security_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` 4.3 Quality Management Specifics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -555,7 +577,6 @@ None 4.4 Quality Management Generic workproducts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - .. list-table:: Quality related work products :header-rows: 1 @@ -566,345 +587,395 @@ None - Link to WP - WP status - * - wp__audit_report + * - :need:`PROCESS_wp__audit_report` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - - - :need:`PROCESS_wp__audit_report` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - `#470 <https://github.com/eclipse-score/score/issues/470>`_ + - <Link to WP> + - <automated> - * - wp__chm_plan + * - :need:`PROCESS_wp__chm_plan` - :need:`PROCESS_gd_guidl__change__change_request` - - valid - - - - :need:`PROCESS_wp__chm_plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__cmpt_request + * - :need:`PROCESS_wp__cmpt_request` - :need:`PROCESS_gd_guidl__change__change_request` - - valid - - - - :need:`PROCESS_wp__cmpt_request` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__component_arch + * - :need:`PROCESS_wp__component_arch` - :need:`PROCESS_gd_guidl__arch__design` - - valid - - - - :need:`PROCESS_wp__component_arch` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__arch__design')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__document_mgt_plan + * - :need:`PROCESS_wp__document_mgt_plan` - :need:`PROCESS_gd_guidl__documentation` - - valid - - n/a - - :need:`PROCESS_wp__document_mgt_plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__documentation')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__fdr_reports + * - :need:`PROCESS_wp__fdr_reports` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__fdr_reports` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__feat_request + * - :need:`PROCESS_wp__feat_request` - :need:`PROCESS_gd_guidl__change__change_request` - - valid - - - - :need:`PROCESS_wp__feat_request` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__feature_arch + * - :need:`PROCESS_wp__feature_arch` - :need:`PROCESS_gd_guidl__arch__design` - - valid - - - - :need:`PROCESS_wp__feature_arch` - - valid - - * - wp__feature_dfa - - - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__arch__design')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__feature_dfa` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__feature_safety_analysis` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__hsi` - n/a - - :need:`PROCESS_wp__feature_dfa` - - valid + - draft + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__feature_safety_analysis - - - - valid - - n/a - - :need:`PROCESS_wp__feature_safety_analysis` - - valid + * - :need:`PROCESS_wp__issue_track_system` + - :need:`PROCESS_gd_guidl__change__change_request` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__hsi - - n/a - - valid - - n/a - - :need:`PROCESS_wp__hsi` - - valid + * - :need:`PROCESS_wp__module_safety_manual` + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__issue_track_system - - :need:`PROCESS_gd_guidl__change__change_request` - - valid - - - - :need:`PROCESS_wp__issue_track_system` - - valid + * - :need:`PROCESS_wp__module_safety_package` + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__module_safety_manual + * - :need:`PROCESS_wp__module_safety_plan` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__module_safety_manual` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__module_sw_release_note` + - :need:`PROCESS_gd_guidl__rel_management` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__rel_management')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__module_sw_release_plan` + - :need:`PROCESS_gd_guidl__rel_management` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__rel_management')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__platform_feature_dfa` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__platform_safety_manual` + - :need:`PROCESS_gd_guidl__saf_plan_definitions` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__module_safety_package + * - :need:`PROCESS_wp__platform_safety_plan` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__module_safety_package` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__module_safety_plan + * - :need:`PROCESS_wp__platform_safety_package` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__module_safety_plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__platform_sw_build_config - - - - + * - :need:`PROCESS_wp__platform_sw_build_config` - n/a - - :need:`PROCESS_wp__platform_sw_build_config` - draft - - * - wp__platform_sw_release_note - - - - + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__platform_sw_release_note` + - :need:`PROCESS_gd_guidl__rel_management` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__rel_management')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__platform_sw_release_plan` + - :need:`PROCESS_gd_guidl__rel_management` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__rel_management')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__policies` - n/a - - :need:`PROCESS_wp__platform_sw_release_note` - - valid - - * - wp__policies - - - - - - n/a - - :need:`PROCESS_wp__policies` - draft + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__prm_plan + * - :need:`PROCESS_wp__prm_plan` - :need:`PROCESS_gd_guidl__problem__problem` - - valid - - n/a - - :need:`PROCESS_wp__prm_plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__problem__problem')` + - <Link to issue> + - <Link to WP> + - <automated> - * - valid - - - - + * - :need:`PROCESS_wp__process_definition` - n/a - - :need:`PROCESS_wp__process_definition` - draft + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__process_impr_report - - :need: gd_guidl__qlm_plan_definitions - - valid - - n/a - - :need: wp__process_impr_report - - valid + * - :need:`PROCESS_wp__process_impr_report` + - :need:`PROCESS_gd_guidl__platform__mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__platform__mgmt_plan')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__process_plan - - - - valid + * - :need:`PROCESS_wp__process_plan` - n/a - - :need:`PROCESS_wp__process_plan` - - valid - - * - wp__project_mgt - - - - valid - - n/a - - :need:`PROCESS_wp__project_mgt` - - valid - - * - wp__qms_plan - - :need: gd_guidl__qlm_plan_definitions - - valid - - n/a - - :need: wp__qms_plan - - valid - - * - wp__qms_report - - :need: gd_guidl__qlm_plan_definitions - - valid - - n/a - - :need: wp__qms_report - - valid - - * - wp__requirements__comp + - draft + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__project_mgt` + - :need:`PROCESS_gd_guidl__platform__mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__platform__mgmt_plan')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__qms_plan` + - :need:`PROCESS_gd_guidl__qlm_plan_definitions` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__qlm_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__qms_report` + - :need:`PROCESS_gd_guidl__qlm_plan_definitions` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__qlm_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__requirements__comp` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__comp` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__requirements__comp_aou + * - :need:`PROCESS_wp__requirements__comp_aou` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__comp_aou` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__requirements__feat + * - :need:`PROCESS_wp__requirements__feat` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__feat` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__requirements__feat_aou + * - :need:`PROCESS_wp__requirements__feat_aou` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__feat_aou` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__requirements__inspect + * - :need:`PROCESS_wp__requirements__inspect` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__inspect` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__requirements__stkh + * - :need:`PROCESS_wp__requirements__stkh` - :need:`PROCESS_gd_guidl__req__engineering` - - valid - - n/a - - :need:`PROCESS_wp__requirements__stkh` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__req__engineering')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__sw_arch_verification + * - :need:`PROCESS_wp__sw_arch_verification` - :need:`PROCESS_gd_guidl__arch__design` - - valid - - n/a - - :need:`PROCESS_wp__sw_arch_verification` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__arch__design')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__sw_component_class + * - :need:`PROCESS_wp__sw_component_class` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__sw_component_class` - - valid - - * - wp__sw_component_dfa - - - - valid - - n/a - - :need:`PROCESS_wp__sw_component_dfa` - - valid - - * - wp__sw_component_safety_analysis - - - - valid - - n/a - - :need:`PROCESS_wp__sw_component_safety_analysis` - - valid - - * - wp__sw_development_plan + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__sw_component_dfa` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__sw_component_safety_analysis` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__sw_development_plan` - :need:`PROCESS_gd_guidl__implementation` - - valid - - n/a - - :need:`PROCESS_wp__sw_development_plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__implementation')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__sw_implementation + * - :need:`PROCESS_wp__sw_implementation` - :need:`PROCESS_gd_guidl__implementation` - - valid - - n/a - - :need:`PROCESS_wp__sw_implementation` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__implementation')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__sw_implementation_inspection + * - :need:`PROCESS_wp__sw_implementation_inspection` - :need:`PROCESS_gd_guidl__implementation` - - valid - - n/a - - :need:`PROCESS_wp__sw_implementation_inspection` - - valid - - * - wp__tailoring - - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__tailoring` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__implementation')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__tailoring_platform + * - :need:`PROCESS_wp__tailoring` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - - valid - - n/a - - :need:`PROCESS_wp__tailoring` - - valid - - * - wp__tool_verification - - - - + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__tlm_plan` + - :need:`PROCESS_need_concept__tool__process` + - :ndf:`copy('status', need_id='PROCESS_doc_concept__tool__process')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__tool_verification_report` + - :need:`PROCESS_doc_concept__tool__process` + - :ndf:`copy('status', need_id='PROCESS_doc_concept__tool__process')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__training_path` - n/a - - :need:`PROCESS_wp__tool_verification_report` - - valid - - * - wp__training_path - - - - - - n/a - - :need:`PROCESS_wp__training_path` - draft + - <Link to issue> + - <Link to WP> + - <automated> + - * - wp__verification__comp_int_test + * - :need:`PROCESS_wp__verification__comp_int_test` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__comp_int_test` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__feat_int_test + * - :need:`PROCESS_wp__verification__feat_int_test` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__feat_int_test` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__module_ver_report + * - :need:`PROCESS_wp__verification__module_ver_report` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__module_ver_report` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__plan + * - :need:`PROCESS_wp__verification__plan` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__plan` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__platform_test + * - :need:`PROCESS_wp__verification__platform_test` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__platform_test` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__platform_ver_report + * - :need:`PROCESS_wp__verification__platform_ver_report` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__platform_ver_report` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> - * - wp__verification__sw_unit_test + * - :need:`PROCESS_wp__verification__sw_unit_test` - :need:`PROCESS_gd_guidl__verification_guide` - - valid - - n/a - - :need:`PROCESS_wp__verification__sw_unit_test` - - valid + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__verification_guide')` + - <Link to issue> + - <Link to WP> + - <automated> From 39f22e26322039667de0f34991c858c64f13695e Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 17 Jun 2025 00:27:11 +0200 Subject: [PATCH 045/102] process: include review findings Ref: closes #1211 --- .../quality_management.rst | 332 ++---------------- 1 file changed, 24 insertions(+), 308 deletions(-) diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index 017fddf14b..d7b4f8914c 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -30,7 +30,7 @@ This includes an approach to providing an independent and objective assurance th comply with predefined provisions and plans and that non-conformances are resolved and further prevented. This document includes quality assurance activities, roles and responsibilities, goals, schedule, etc. and a general strategy to implement quality assurance process in this platform. The quality assurance is -ensured by automated checks and restrictions, manual checks which inculdes to proof that there is no manipulation +ensured by automated checks and restrictions, manual checks which includes to proof that there is no manipulation of the workflows. Statement of Independence @@ -63,7 +63,7 @@ Objectives and scope - ISO/SAE 21434:2021 - 2021 * - 4 - - ISO PAS 8926:2024 + - ISO PAS 8926:2024 (will be integrated into ISO 26262 3rd edition as updated part 8 clause 12) - 2024 @@ -143,316 +143,33 @@ Objectives and scope - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - 100% of the quality improvement, non-conformance issues are closed - None - - Ensured by the process quality management, :need:`PROCESS_wp__issue_track_system` contain improvments and non-coformancees + - Ensured by the process quality management, :need:`PROCESS_wp__issue_track_system` contain improvements and non-conformances 3.4 Work Product Quality Goals ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: Work Product Quality Goals - :header-rows: 1 +For all generated work products, the following quality goals are defined: - * - # - - **Work Product** - - **Quality Criteria** - - **Target value** - - **Allowed variation** - - **Metric** - * - 1 - - :need:`PROCESS_wp__feat_request` - - | Feature request is reviewed and accepted - - 100% - - None - - Ensured by the process quality management, :need:`PROCESS_wp__issue_track_system` contain improvements and non-coformances with a set due date - * - 2 - - :doc:`../requirements/stakeholder/index` - - | All stakeholder requirements are reviewed and valid - | All stakeholder requirements are at least satisfied by one feature requirement - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 3 - - :need:`PROCESS_wp__tool_verification_report` - - | All tool requirements are reviewed and valid - | All tool requirements have bidirectional traceability to and from process requirements or guidance - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 4 - - :need:`PROCESS_wp__requirements__feat` - - | All feature requirements are reviewed and valid - | All feature requirements have bidirectional traceability to and from stakeholder requirements - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 5 - - :need:`PROCESS_wp__requirements__comp` - - | All component requirements are reviewed and valid - | All component requirements have bidirectional traceability to and from feature requirements - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 6 - - :need:`PROCESS_wp__requirements__feat_aou` - - | All feature aou are reviewed and valid - | All feature aou have bidirectional traceability to and from feature requirements - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 7 - - :need:`PROCESS_wp__requirements__comp_aou` - - | All component aou are reviewed and valid - | All component aou have bidirectional traceability to and from feature requirements - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 8 - - :need:`PROCESS_wp__hsi` - - | Hardware and Software interaction is specified and consistent with the technical safety concept - | All component HW parts that are controlled by the software are included - | All HW resources that support the SW execution are included - - 100% - - None - - Ensured by quality management, only verified and valid documents can be merged, review required - * - 9 - - :need:`PROCESS_wp__requirements__inspect` - - | All requirements were inspected by review with inspection checklist. - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 10 - - :need:`PROCESS_wp__feature_arch` - - | All feature architectures are reviewed and valid - | All feature architectures have bidirectional traceability to and from feature requirements - - 100% - - None - - Ensured by process configuration and tool management, only valid requirements can be merged, review required, script based check - * - 11 - - :need:`PROCESS_wp__feature_safety_analysis` - - | Inductive (bottom-up) safety analysis e.g. FMEA is completed. Analysis verifies the feature architecture. - | All detection and prevention mitigations are linked to Software Feature Requirements or Assumptions of use. - - 100% - - None - - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 12 - - :need:`PROCESS_wp__component_arch` - - | All component architectures are reviewed and valid - | All component architectures have bidirectional traceability to and from components requirements or feature architectures - - 100% - - None - - Ensured by process configuration and tool management, only valid architecture can be merged, review required, script based check - * - 13 - - :need:`PROCESS_wp__sw_component_safety_analysis` - - | Inductive (bottom-up) safety analysis e.g. FMEA is completed. Analysis verifies the component architecture. - | All detection and prevention mitigations are linked to Software Component Requirements or Assumptions of use. - - 100% - - None - - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 14 - - :need:`PROCESS_wp__sw_arch_verification` - - | Architecture verification is available and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid architecture can be merged, review required, script based check - * - 15 - - :need:`PROCESS_wp__sw_implementation` - - | Implementation of source code has been done after creation of detailed design. - | SW configuration is described. - - 100% - - None - - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check - * - 16 - - :need:`PROCESS_wp__verification__sw_unit_test` - - | Detailed design is verified by unit testing. - - 100% - - None - - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check - * - 17 - - :need:`PROCESS_wp__sw_implementation_inspection` - - | Inspection is done by inspection checklist. - - 100% - - None - - Ensured by process configuration and tool management, only valid Detailed Design and Code can be merged, verification required, script based check - * - 18 - - :need:`PROCESS_wp__verification__feat_int_test` - - | All interfaces from static view and all flows from dynamic view are valid and reviewed. - | Performance expectations (RAM, processor usage, ..) on reference hardware are described. - - 100% - - None - - Ensured by process configuration and tool management, only valid features can be merged, verification required, script based check - * - 19 - - :need:`PROCESS_wp__verification__comp_int_test` - - | All interfaces from static view and all flows from dynamic view are valid and reviewed. - | Integration of units into components is based on the detailed design. - - 100% - - None - - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check - * - 20 - - :need:`PROCESS_wp__verification__module_ver_report` - - | Module verification report is available and valid for every module. - - 100% - - None - - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check - * - 21 - - :need:`PROCESS_wp__sw_component_class` - - | Software component classification is available and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid components can be merged, verification required, script based check - * - 22 - - :need:`PROCESS_wp__training_path` - - | All training material is available and valid, training planned and executed - | All training paths have been scheduled and executed - - 100% - - None - - Ensured by process platform management, evidences for participants available, feedback of participants documented - * - 23 - - :need:`PROCESS_wp__issue_track_system` - - All issues follow the planning strategy defined in the project/platform management plan - - 100% - - None - - Ensured by project management and tool management, only issues following the strategy can be part of any PR - * - 24 - - :need:`PROCESS_wp__platform_mgmt` - - All findings from work product review are resolved anf reviewed. Document is valid. - - 100% - - None - - Ensured by project management, only verified and valid documents can be merged, review required - * - 25 - - :need:`PROCESS_wp__process_definition` - - All findings from platform audit are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by process management and tool management, only verified and valid documents can be merged, review required - * - 26 - - :need:`PROCESS_wp__process_impr_report` - - Process improvement report is available and valid for every platform release. - - 100% - - None - - Ensured by quality management and tool management, only verified and valid documents can be merged, review required - * - 27 - - :need:`PROCESS_wp__process_plan` - - The process strategy is defined, available and valid. - - 100% - - None - - Ensured by process management and tool management, only verified and valid documents can be merged, review required - * - 28 - - :need:`PROCESS_wp__module_safety_plan` - - All findings from work product review are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 29 - - :need:`PROCESS_wp__module_safety_package` - - All findings from work product review are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 30 - - :need:`PROCESS_wp__module_safety_package` - - All findings from work product review are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 31 - - :need:`PROCESS_wp__platform_safety_plan` - - All findings from work product review are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 32 - - :need:`PROCESS_wp__platform_safety_package` - - All findings from work product review are resolved and reviewed. Document is valid. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 33 - - :need:`PROCESS_wp__fdr_reports` - - CMR reports (Safety Plan, Safety Case, Safety Analyses and DFA) are available and valid for every platform release. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 34 - - :need:`PROCESS_wp__audit_report` - - Process Safety Audit report is available and valid for every platform release. - - 100% - - None - - Ensured by safety management, only verified and valid documents can be merged, review required - * - 35 - - :need:`PROCESS_wp__platform_feature_dfa` - - | DFA on platform feature level is available and valid. - | All detection and prevention mitigations linked to Software Feature Requirements or Assumptions of Use. - - 100% - - None - - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 36 - - :need:`PROCESS_wp__feature_dfa` - - | DFA on feature level is available and valid. - | All detection and prevention mitigations linked to Software Feature Requirements or Assumptions of Use. - - 100% - - None - - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 37 - - :need:`PROCESS_wp__sw_component_dfa` - - | DFA on component/module level is available and valid. - | All detection and prevention mitigations linded to Software Component Requirements or Assumptions of Use. - - 100% - - None - - Ensured by process configuration and tool management, only valid safety analysis can be merged, review required, script based check - * - 38 - - :need:`PROCESS_wp__module_sw_build_config` - - | Build configuration is capable to create the SEooC Library on the reference HW, module level. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 39 - - :need:`PROCESS_wp__module_safety_manual` - - | Safety Manual for every module is available, up to date and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 40 - - :need:`PROCESS_wp__module_sw_release_note` - - | All known bugs are described with a clear statement that these bugs do not lead to violation of any safety requirements or corresponding workaround measures. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 41 - - :need:`PROCESS_wp__sw_development_plan` - - | SW Development Plan is available, up to date and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 42 - - :need:`PROCESS_wp__verification__plan` - - | Verification Plan is available, up to date and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 43 - - :need:`PROCESS_wp__tlm_plan` - - | Tool Management Plan is available, up to date and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 44 - - :need:`PROCESS_wp__tool_verification_report` - - | All tool conficence levels (TCL) are determined. Appropriate qualification methods are applied. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 45 - - :need:`PROCESS_wp__tailoring` - - | Argumentation for all tailored (not needed) work products in the project is available and valid. - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check - * - 46 - - :need:`PROCESS_wp__qms_plan` - - | Quality Management Plan is available, up to date and valid - - 100% - - None - - Ensured by process configuration and tool management, only valid documents can be merged, review required, script based check +**Quality Criteria** + +All work products have to be available and valid. Templates, checklists, and guidelines shall be used. +Plans have to be up to date. + +The training material shall be available in the training path. +The issues in the issue tracking system following the planning strategy. + +**Target value** + +The target value for all work products is 100%. + +**Allowed variation** + +There is no allowed variation for the work products. + +**Metric** + +The metric for the work products is ensured by the process that contains the work product. Only valid work products can be merged. Reviews are required and therefore checklists are prepared. If applicable, script based checks are implemented. 3.5 Quality Management Scope ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -559,8 +276,7 @@ Ad-hoc quality related meetings are set up for clarification topics. **Reporting** -The quality management status is reported as defined in the platform management plan. The status report includes -at least the defined Quality Criteria defined in this document. +The quality management status :need:`PROCESS_wp__qms_report` is reported as defined in the platform management plan. **Escalation** From edf8d9fa08203f8086c531a172b44d93c85332f3 Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 17 Jun 2025 09:00:34 +0200 Subject: [PATCH 046/102] process: add org diagram Ref: closes #316 --- .../score_project_organisation.drawio.svg | 230 ++++++++++++++++++ .../quality_management.rst | 9 +- 2 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 docs/platform_management_plan/_assets/score_project_organisation.drawio.svg diff --git a/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg b/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg new file mode 100644 index 0000000000..596e88b21c --- /dev/null +++ b/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg @@ -0,0 +1,230 @@ +<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="711px" height="381px" viewBox="-0.5 -0.5 711 381" content="<mxfile><diagram id="rtrJPRNpxuqNjPrvO07C" name="Page-1">7Vnbdto6EP0aHmH5goE8cj19aFbSwjltH4UtsFpZYskixvn6juwxtjEhOYEkTVeesLZHtz17NNbQcsfR7h9FNuG1DChvOVawa7mTluPYXW8APwZJc6Tb6+XAWrEAjUpgzu4pghaiWxbQuGaopeSabeqgL4Wgvq5hRCmZ1M1Wktdn3ZA1bQBzn/Am+o0FOszRgWeV+CfK1mExs23hm4gUxgjEIQlkUoHcacsdKyl1/hTtxpQb8gpe8n6zB97uF6ao0E/p4OQd7gjf4t7m45uvU1ycTosdxwmLOBHQGoU64gDa8BhrojS6ByaCd1Kxeyk0KSx802CCqkW6MVZaUTPGmpPY+MD0wRVQpenuwV3Ye25AVFRGVKsUTLBD23aRz7SQGLaT0j39Qj1hxTXuAEGCkljvBy9Zgwck7jiJboPEBn80AAFhUyodyrUUhE9LdKTkVgQ0QFJKm89SbpDMn1TrFOkmWy2POGNo1A2AkJmvMmzGzMorXJvFPMh0sXa5VT5aYbTCWGuKVv3j/lCUE83u6qOfQ233CdSKoNj1kkv/1yJkArYKMG7ckLMCHSJztmlX/UH5UiZVV2QAvDCaZL7R8oF36I7p7+a542HrB85jnie7itkkPYv6fpP63itR731Qf0j91ctQ/29M1c3yp8lUjsXJkvK864L6ochYMKksiraCaQZ5LxtfkAgnnN4RAcB/kJ407kzGYClF/v7TV4AmTMH4UuUG4CxSGtysVgx27VgYbTQiDJcAc3QtuiPRhtMOrAHH58SnIWRNquqZlDPxKwdCrU0yHpo9O7MkSTqBIkmHydywEFlVzKi/ir6QixGL8oRcH9QPhNthkGFWDASi8uXNAqIJ/BgcmJptgds2uQNQxW1Y5cyzHYTj9lUbUocz6GzEGmZJQqbpfEMyASTw5VI/X+s6rGYwk9RmwAYzw2S2BrmWdyXwpCTnnExy/XqKc46kOHtwJMU9I8NBs6LJJ2uUUxIYqTLlgwcPVLqgcQyOsa7hZKDqmE7Hs5uT6rTPVWchuv6bis69lORqAmtq8AKSs/veo59VRzXXf1HN3SpZgO9EcYMPxT1PcX+G4GaU6K0yilhQEjUS8JCzWJoUPJFCZsm4KbV5GmsKjrOGQcTESdW5r56Fr95UnhfJwRfQ3j5T/lkZ9suWcKbNOq+JAA+ov+n7z7beVHrv6gOwe/Wm+mwWm3AHr1vmALJU+r3aMBdAvA6aZnkHzFrFJTAgcZjNW9wVm7fI/cXxgrfIouh0yeJJ1hUu3iStGGwkEzqujHxrgFI93sHpVmTa0v/5iKUa9kt7UrnAxs1X6gXTGO4F+TljeAKNHtPLZ4zxio/hwFubs8kHZuG8c0dFOWCILyIWBLmcaMzuyTIbzzgJWYDBvVHLm5wKPCwOY+fWviRbKzuerjtaHbtflKj+n/ea7ql3kKtVjKf57PkucT8C9FkBOjju9dcN0EvHZ7OU+hfEp/tIfHZ7dv1C0XYuEq7OQSp+iej13jR6KwH7o/rugegtA9YdDKqV2Y7lDk6GrWncUsWAGqOl5llgGrdEw1uRIeZefsloP7eq+7xo79UV5PYO/qg7sHf7J+3PPx56jeNhDB/QW27WcPT++56OCe+xNL7/pymtDX7mKVEk4HPOBWiWfwfn5uWf6u70Nw==</diagram></mxfile>"> + <defs/> + <g> + <g> + <path d="M 0 20 L 0 0 L 710 0 L 710 20" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 0 20 L 0 380 L 710 380 L 710 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 0 20 L 710 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 10px; margin-left: 355px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; "> + SCORE + </div> + </div> + </div> + </foreignObject> + <text x="355" y="14" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold"> + SCORE + </text> + </switch> + </g> + </g> + <g> + <path d="M 265 110 L 265 130 L 265 120 L 265 133.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 265 138.88 L 261.5 131.88 L 265 133.63 L 268.5 131.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <path d="M 265 210 L 265 225 L 160 225 L 160 231.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 160 238.88 L 157.67 231.88 L 162.33 231.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <path d="M 265 210 L 265 225 L 370 225 L 370 231.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 370 238.88 L 367.67 231.88 L 372.33 231.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <a xlink:href="https://www.draw.io"> + <g> + <rect x="70" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="76.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 124px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> + Technical communities + </div> + </div> + </div> + </foreignObject> + <text x="124" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Technical communities + </text> + </switch> + </g> + </g> + </a> + <g> + <rect x="175" y="140" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="181.5" y="153.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 175px; margin-left: 229px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> + Technical lead circle + </div> + </div> + </div> + </foreignObject> + <text x="229" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Technical lead circle + </text> + </switch> + </g> + </g> + <g> + <rect x="175" y="40" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="181.5" y="53.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 75px; margin-left: 229px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> + Project lead circle + </div> + </div> + </div> + </foreignObject> + <text x="229" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Project lead circle + </text> + </switch> + </g> + </g> + <a xlink:href="https://www.draw.io"> + <g> + <rect x="280" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="286.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-2-128.png" preserveAspectRatio="none"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 334px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> + Feature Teams + </div> + </div> + </div> + </foreignObject> + <text x="334" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Feature Teams + </text> + </switch> + </g> + </g> + </a> + <a xlink:href="https://www.draw.io"> + <g> + <rect x="490" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="496.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 544px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> + <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> + Quality Manager + </div> + </div> + </div> + </foreignObject> + <text x="544" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Quality Manager + </text> + </switch> + </g> + </g> + </a> + <g> + <path d="M 580 240 L 580 175 L 361.37 175" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 356.12 175 L 363.12 171.5 L 361.37 175 L 363.12 178.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 176px; margin-left: 481px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> + <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> + Escalation path + </div> + </div> + </div> + </foreignObject> + <text x="481" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + Escalation path + </text> + </switch> + </g> + </g> + <g> + <path d="M 580 240 L 580 75 L 361.37 75" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 356.12 75 L 363.12 71.5 L 361.37 75 L 363.12 78.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 481px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> + <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> + Escalation path + </div> + </div> + </div> + </foreignObject> + <text x="481" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + Escalation path + </text> + </switch> + </g> + </g> + <g> + <path d="M 559.84 323.04 L 559.8 360 L 370 360 L 370 326.37" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="1 1" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 370 321.12 L 373.5 328.12 L 370 326.37 L 366.5 328.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + </g> + <g> + <g transform="translate(-0.5 -0.5)"> + <switch> + <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 362px; margin-left: 460px;"> + <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> + <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> + Consult Feature Teams + </div> + </div> + </div> + </foreignObject> + <text x="460" y="365" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + Consult Feature Teams + </text> + </switch> + </g> + </g> + </g> + <switch> + <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/> + <a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"> + <text text-anchor="middle" font-size="10px" x="50%" y="100%"> + Text is not SVG - cannot display + </text> + </a> + </switch> +</svg> diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index d7b4f8914c..cec34028a4 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -40,6 +40,11 @@ The :need:`PROCESS_rl__quality_manager` provides only support to the project wit quality of the project/platform product. Although the quality report is also sent to the :need:`PROCESS_rl__technical_lead`, the :need:`PROCESS_rl__quality_manager` is independent of the delivery of the product. + .. image:: _assets/score_project_organisation.drawio.svg + :width: 900 + :alt: Project Organization + :align: center + Objectives and scope -------------------- @@ -222,7 +227,7 @@ Organization and management system is currently not mature. **Skills** -The main quality related project roles are the Project Lead :need:`PROCESS_rl__project_lead` and the Quality Manager :need:`PROCESS_rl__quality_manager` and these also have to have +The main quality related project roles are are the Quality Manager :need:`PROCESS_rl__quality_manager` and and the Technical Lead :need:`PROCESS_rl__technical_lead`. These also have to have the (Eclipse) committer role. As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. @@ -270,7 +275,7 @@ possible and follows the defined processes. To exchange general information and to clarify general topics, the following communication channels are used: - Regular (online) meetings - E-Mails -- Messager Services e.g., Slack, Microsoft Teams, Github Notifications +- Messenger Services e.g., Slack, Microsoft Teams, Github Notifications Ad-hoc quality related meetings are set up for clarification topics. From 3e70cdd6298f7710bf6a818a8490b6de988a4118 Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 17 Jun 2025 12:01:55 +0200 Subject: [PATCH 047/102] process: include review findings Ref: closes#316 --- .../score_project_organisation.drawio.svg | 105 +++++++++--------- .../quality_management.rst | 33 +++--- .../safety_management.rst | 4 +- 3 files changed, 70 insertions(+), 72 deletions(-) diff --git a/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg b/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg index 596e88b21c..191e43a5e2 100644 --- a/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg +++ b/docs/platform_management_plan/_assets/score_project_organisation.drawio.svg @@ -1,74 +1,71 @@ -<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="711px" height="381px" viewBox="-0.5 -0.5 711 381" content="<mxfile><diagram id="rtrJPRNpxuqNjPrvO07C" name="Page-1">7Vnbdto6EP0aHmH5goE8cj19aFbSwjltH4UtsFpZYskixvn6juwxtjEhOYEkTVeesLZHtz17NNbQcsfR7h9FNuG1DChvOVawa7mTluPYXW8APwZJc6Tb6+XAWrEAjUpgzu4pghaiWxbQuGaopeSabeqgL4Wgvq5hRCmZ1M1Wktdn3ZA1bQBzn/Am+o0FOszRgWeV+CfK1mExs23hm4gUxgjEIQlkUoHcacsdKyl1/hTtxpQb8gpe8n6zB97uF6ao0E/p4OQd7gjf4t7m45uvU1ycTosdxwmLOBHQGoU64gDa8BhrojS6ByaCd1Kxeyk0KSx802CCqkW6MVZaUTPGmpPY+MD0wRVQpenuwV3Ye25AVFRGVKsUTLBD23aRz7SQGLaT0j39Qj1hxTXuAEGCkljvBy9Zgwck7jiJboPEBn80AAFhUyodyrUUhE9LdKTkVgQ0QFJKm89SbpDMn1TrFOkmWy2POGNo1A2AkJmvMmzGzMorXJvFPMh0sXa5VT5aYbTCWGuKVv3j/lCUE83u6qOfQ233CdSKoNj1kkv/1yJkArYKMG7ckLMCHSJztmlX/UH5UiZVV2QAvDCaZL7R8oF36I7p7+a542HrB85jnie7itkkPYv6fpP63itR731Qf0j91ctQ/29M1c3yp8lUjsXJkvK864L6ochYMKksiraCaQZ5LxtfkAgnnN4RAcB/kJ407kzGYClF/v7TV4AmTMH4UuUG4CxSGtysVgx27VgYbTQiDJcAc3QtuiPRhtMOrAHH58SnIWRNquqZlDPxKwdCrU0yHpo9O7MkSTqBIkmHydywEFlVzKi/ir6QixGL8oRcH9QPhNthkGFWDASi8uXNAqIJ/BgcmJptgds2uQNQxW1Y5cyzHYTj9lUbUocz6GzEGmZJQqbpfEMyASTw5VI/X+s6rGYwk9RmwAYzw2S2BrmWdyXwpCTnnExy/XqKc46kOHtwJMU9I8NBs6LJJ2uUUxIYqTLlgwcPVLqgcQyOsa7hZKDqmE7Hs5uT6rTPVWchuv6bis69lORqAmtq8AKSs/veo59VRzXXf1HN3SpZgO9EcYMPxT1PcX+G4GaU6K0yilhQEjUS8JCzWJoUPJFCZsm4KbV5GmsKjrOGQcTESdW5r56Fr95UnhfJwRfQ3j5T/lkZ9suWcKbNOq+JAA+ov+n7z7beVHrv6gOwe/Wm+mwWm3AHr1vmALJU+r3aMBdAvA6aZnkHzFrFJTAgcZjNW9wVm7fI/cXxgrfIouh0yeJJ1hUu3iStGGwkEzqujHxrgFI93sHpVmTa0v/5iKUa9kt7UrnAxs1X6gXTGO4F+TljeAKNHtPLZ4zxio/hwFubs8kHZuG8c0dFOWCILyIWBLmcaMzuyTIbzzgJWYDBvVHLm5wKPCwOY+fWviRbKzuerjtaHbtflKj+n/ea7ql3kKtVjKf57PkucT8C9FkBOjju9dcN0EvHZ7OU+hfEp/tIfHZ7dv1C0XYuEq7OQSp+iej13jR6KwH7o/rugegtA9YdDKqV2Y7lDk6GrWncUsWAGqOl5llgGrdEw1uRIeZefsloP7eq+7xo79UV5PYO/qg7sHf7J+3PPx56jeNhDB/QW27WcPT++56OCe+xNL7/pymtDX7mKVEk4HPOBWiWfwfn5uWf6u70Nw==</diagram></mxfile>"> +<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="902px" height="402px" viewBox="-0.5 -0.5 902 402" content="<mxfile><diagram id="rtrJPRNpxuqNjPrvO07C" name="Page-1">7Vnbdps6EP0aP9qLi6+PvrYPzXJOk3PpowKyUSskLyGCna8/IxgMGNtxY5K0XXkCbY0u7NmjkUTLnYbbT4psghvpU95yLH/bcmctx7FHVhceBtllSL/fz4C1Yj4aFcAde6IIWojGzKdRxVBLyTXbVEFPCkE9XcGIUjKpmq0kr466IWtaA+48wuvov8zXQYYOe1aBf6ZsHeQj2xbWhCQ3RiAKiC+TEuTOW+5USamzt3A7pdyQl/OStVucqN1PTFGhL2qAxD8SHuPH3U2XX+cALdWaCPZENJMCJ6t3OQNRwkJOBJQmgQ45gDa8Rpooje6CgaFOKvYkhSa5hWcKTFB1v9sYK62o6WPNSWR8YtrghKjSdHvyq+w9VyAyKkOq1Q5MsEHbzflFgdldLCeFu0a5U4KSq7o5SFAi633nBYvwgkSeIHVQI7VGIPVBUViUSgdyLQXh8wKdKBkLn/rISmHzRcoNsvmdar1Dvkms5RFvjI3cARAydVaKLZiZetotFf6BRTZTM73T5KNoIhkrD83yT4T+1xTtTnlJUQ6qeqwOcBXhwwsIr30pIMiEYWsFykQqbVMuO4jyB5mUfZMCUGFUyjyj7gN30S3T/5n3Tg9L33Ac8z7blsxmOywc+ualnrCPeMJ6K0+MPjxx3hPu63ji74iq5cN3k+0ci5MHyrOmkEtgZYUcFwvPrOTEeGtFiY4VNVOjJIyywQQJcfT5I4EV3/oH8p3GL5URS/NAWv/5K0AzpmAwqTIDLj1SGCxXK+aZ7jHP05AwnA+M0bXoloQbTjueDLF/TjwaQBqmqpqaORM/MiDQ2mT3sSHAWSRJ0vEVSTpMZoa5ACtKR3GWtIfMTFiYpfhqr54v3A6DHLVioCCVzW/hE03gYXCgahED023yCKCK2jDNRc92EI7ao7bTtp1hZyPWMEoSME3vNiQVRAJ7oeoCXRVqOQeatLgAOpjpJrU1yI18LIDL0mT/bJ50htU06RxJk/bwSJoc/nyWhGJJo2c1e0+9QKTBDDAlvtnJMeWBDw+Eek+jCFxj3UCoUnVMqtPF8qxA7WsFuted/a66c5tSXUVjdRk2oTp32Ht2c3ZUdYNXVd2tkjn4u2jO+dDcCzX3a0huKsMwFiAdWsvBY84ic+6yZlLINB/XhXa3izQFr1ljP2TirObct0/E7ruKs5E03ITyuqNfMsf+FRPOtJnnDRHgAvVHbQK7H5vAy+9KrKpA3eGbCrR2hHRwpX7byxJgS+1K50RT/FauK06KaSk/KhbHS3c4LB8wO5abl48fMk3hlioGnEH0ZZhPoiD9ChsLt0RDrUgRs3O47Czaqh9FMQgbvRRIm8JRnuxKBhvJhI5KPd8aoKQ3x63qrWcdXFEeNOidNYeXbAaF3PafctGNhVO/AZ1CjMdcnzooHwjzC64mJTHB0ro2PvPAJca3k/x2YowVIfP9TLc0Yk/kIe3PCADZg857k1Zvdi7E8XIbG7f2V8plJWSxdDL2rY69V8au0vnPaaDmM9uttpCrVYRpZPFyTw3ed2EoLwulVeLEwlAJ5eOXUNbZ9aHBQHeOq+C1A90+2PnYvWYjt37rO48gyPCPBTAF6eu3i9jBMxHb7dvVo0zbaSRk2/lfi4Numw3h0UcIvyyEr/2V0kwIuw2HcL4V+LNCePRc0h3kLr4yZnvXhygUi7/NmXnxz96d/w8=</diagram></mxfile>"> <defs/> <g> <g> - <path d="M 0 20 L 0 0 L 710 0 L 710 20" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 0 20 L 0 380 L 710 380 L 710 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 0 20 L 710 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 0 20 L 0 0 L 900 0 L 900 20" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 0 20 L 0 400 L 900 400 L 900 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 0 20 L 900 20" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 10px; margin-left: 355px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 10px; margin-left: 450px;"> <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap; "> - SCORE + SCORE Organization </div> </div> </div> </foreignObject> - <text x="355" y="14" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold"> - SCORE + <text x="450" y="14" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold"> + SCORE Organization </text> </switch> </g> </g> <g> - <path d="M 265 110 L 265 130 L 265 120 L 265 133.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 265 138.88 L 261.5 131.88 L 265 133.63 L 268.5 131.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 475 110 L 475 130 L 475 120 L 475 140" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> - <path d="M 265 210 L 265 225 L 160 225 L 160 231.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 160 238.88 L 157.67 231.88 L 162.33 231.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 475 210 L 475 225.43 L 370 225.43 L 370 240" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> - <path d="M 265 210 L 265 225 L 370 225 L 370 231.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 370 238.88 L 367.67 231.88 L 372.33 231.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 475 210 L 475 225.43 L 580 225.43 L 580 240" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <a xlink:href="https://www.draw.io"> <g> - <rect x="70" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <image x="76.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> + <rect x="280" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="286.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 124px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 334px;"> <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> - Technical communities + Cross functional feature teams </div> </div> </div> </foreignObject> - <text x="124" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> - Technical communities + <text x="334" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Cross functional feat... </text> </switch> </g> </g> </a> <g> - <rect x="175" y="140" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <image x="181.5" y="153.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> + <rect x="385" y="140" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="391.5" y="153.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 175px; margin-left: 229px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 175px; margin-left: 439px;"> <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> Technical lead circle @@ -76,21 +73,21 @@ </div> </div> </foreignObject> - <text x="229" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + <text x="439" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> Technical lead circle </text> </switch> </g> </g> <g> - <rect x="175" y="40" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <image x="181.5" y="53.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> + <rect x="385" y="40" width="180" height="70" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="391.5" y="53.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-3-128.png" preserveAspectRatio="none"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 75px; margin-left: 229px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 75px; margin-left: 439px;"> <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> Project lead circle @@ -98,7 +95,7 @@ </div> </div> </foreignObject> - <text x="229" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + <text x="439" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> Project lead circle </text> </switch> @@ -106,23 +103,23 @@ </g> <a xlink:href="https://www.draw.io"> <g> - <rect x="280" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <image x="286.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-2-128.png" preserveAspectRatio="none"/> + <rect x="490" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="496.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-2-128.png" preserveAspectRatio="none"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 334px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 544px;"> <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> - Feature Teams + Communities </div> </div> </div> </foreignObject> - <text x="334" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> - Feature Teams + <text x="544" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + Communities </text> </switch> </g> @@ -130,14 +127,14 @@ </a> <a xlink:href="https://www.draw.io"> <g> - <rect x="490" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <image x="496.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> + <rect x="20" y="240" width="180" height="80" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <image x="26.5" y="258.5" width="42" height="42" xlink:href="vscode-webview://13735n1eiksdkbou2piglo4al897kvostmm2ekup3ac8sn0pficg/proxy?url=https%3A%2F%2Fcdn3.iconfinder.com%2Fdata%2Ficons%2Fuser-avatars-1%2F512%2Fusers-9-2-128.png" preserveAspectRatio="none"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 544px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 126px; height: 1px; padding-top: 280px; margin-left: 74px;"> <div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "> <div style="display: inline-block; font-size: 12px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "> Quality Manager @@ -145,7 +142,7 @@ </div> </div> </foreignObject> - <text x="544" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> + <text x="74" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="12px" font-weight="bold"> Quality Manager </text> </switch> @@ -153,36 +150,36 @@ </g> </a> <g> - <path d="M 580 240 L 580 175 L 361.37 175" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 356.12 175 L 363.12 171.5 L 361.37 175 L 363.12 178.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 89.84 323.04 L 89.86 360 L 370 360 L 370 326.37" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="1 1" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 370 321.12 L 373.5 328.12 L 370 326.37 L 366.5 328.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 176px; margin-left: 481px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 360px; margin-left: 267px;"> <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> - Escalation path + Consult feature teams </div> </div> </div> </foreignObject> - <text x="481" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> - Escalation path + <text x="267" y="363" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + Consult feature teams </text> </switch> </g> </g> <g> - <path d="M 580 240 L 580 75 L 361.37 75" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 356.12 75 L 363.12 71.5 L 361.37 75 L 363.12 78.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 110 240 L 110 75 L 378.63 75" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 383.88 75 L 376.88 78.5 L 378.63 75 L 376.88 71.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 481px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 76px; margin-left: 250px;"> <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> Escalation path @@ -190,30 +187,30 @@ </div> </div> </foreignObject> - <text x="481" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + <text x="250" y="79" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> Escalation path </text> </switch> </g> </g> <g> - <path d="M 559.84 323.04 L 559.8 360 L 370 360 L 370 326.37" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="1 1" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> - <path d="M 370 321.12 L 373.5 328.12 L 370 326.37 L 366.5 328.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 110 240 L 110 175 L 378.63 175" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> + <path d="M 383.88 175 L 376.88 178.5 L 378.63 175 L 376.88 171.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(rgb(0, 0, 0), rgb(255, 255, 255)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> </g> <g> <g transform="translate(-0.5 -0.5)"> <switch> <foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"> - <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 362px; margin-left: 460px;"> + <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 176px; margin-left: 251px;"> <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> - Consult Feature Teams + Escalation path </div> </div> </div> </foreignObject> - <text x="460" y="365" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> - Consult Feature Teams + <text x="251" y="179" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> + Escalation path </text> </switch> </g> diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index cec34028a4..5ecb7d10f8 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -45,6 +45,9 @@ the :need:`PROCESS_rl__quality_manager` is independent of the delivery of the pr :alt: Project Organization :align: center +In SCORE we have different Tier and OEM stakeholder involved: Every solution will be checked by the other stakeholders. +This is another strong independent mechanism to ensure Quality. + Objectives and scope -------------------- @@ -82,22 +85,22 @@ Objectives and scope - **Activities** - **Cadence** * - 1 - - Platform Process audit + - Platform process audit - Once for every platform release or on demand * - 2 - - Feature Process conformance checks + - Feature process conformance checks - Once for every feature release * - 3 - - Feature Work product review + - Feature work product review - Once for every feature release * - 4 - - Platform Release verification and approval + - Platform release verification and approval - Once for every release * - 5 - - Process consulting / Quality Trainings + - Process consulting / Quality trainings - Continuously * - 6 - - Process monitoring / Process Improvement + - Process monitoring / Process improvement - Continuously @@ -114,9 +117,9 @@ Objectives and scope - **Allowed variation** - **Metric** * - 1 - - One platform process audit per release + - One Platform process audit per release - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - - 100% of the platform process audit has be done for every release + - 100% of the Platform process audit has be done for every release - Delta audit allowed to achieve 100% - Ensured by the process process management, :need:`PROCESS_wp__process_impr_report` - Platform process audit is available * - 2 @@ -227,7 +230,7 @@ Organization and management system is currently not mature. **Skills** -The main quality related project roles are are the Quality Manager :need:`PROCESS_rl__quality_manager` and and the Technical Lead :need:`PROCESS_rl__technical_lead`. These also have to have +The main quality related project roles are the Quality Manager :need:`PROCESS_rl__quality_manager` and the Technical Lead :need:`PROCESS_rl__technical_lead`. These also have to have the (Eclipse) committer role. As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. @@ -239,11 +242,10 @@ his knowledge in quality SW development by: Additionally, the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull request modifying a file in their area of responsibility before it gets merged. In case of quality related "CODEOWNER" sections (e.g. -any documentation artefacts) the persons having "CODEOWNER" rights need to have: - -- At least one year of professional practice of quality related SW development (or management) relevant for the section content with demonstrable and verifiable results. +any documentation artefacts) the persons having "CODEOWNER" rights need to be qualified according to the roles description +Quality Manager :need:`PROCESS_rl__quality_manager`. -The successful checking of committers and CODEOWNERS skills is ensured by the project and Quality Manager :need:`PROCESS_rl__quality_manager` and documented +The successful checking of committers and CODEOWNERS skills is ensured by the Project and Quality Manager :need:`PROCESS_rl__quality_manager` and documented in the role assignment document. .. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the Quality Manager :need:`PROCESS_rl__quality_manager` role for the approvals @@ -257,8 +259,7 @@ Project Lead :need:`PROCESS_rl__project_lead`, and all other stakeholders, will analyzed, verified, tested, and managed throughout the life cycle of the project. As all the implementation takes place within feature development, there is a Quality Manager :need:`PROCESS_rl__quality_manager` appointed in the feature development plan. -Resources and milestones are planned in Github Issues for all activities. There are issue templates for sagas -(covering one feature development) and for epics (covering one development workproduct each). Resource and +Resources and milestones are planned in Github Issues for all activities. Resource and milestone planning is done as defined in the :doc:`project_management`. **Tools** @@ -631,7 +632,7 @@ None - <automated> * - :need:`PROCESS_wp__tlm_plan` - - :need:`PROCESS_need_concept__tool__process` + - :need:`PROCESS_doc_concept__tool__process` - :ndf:`copy('status', need_id='PROCESS_doc_concept__tool__process')` - <Link to issue> - <Link to WP> diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index 4b3c12318d..c3c59bc537 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -251,7 +251,7 @@ is determined by Safety Audit and not be Eclipse project reviews. Functional Safety Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Requirement Engineering is defined in the process description. See :need:`PROCESS_doc_concept__req__process`. +Requirement Engineering is defined in the process description. See :need:`doc__project_mgt_plan`. The application of ISO 26262 standards requirements is realized by defining process guidances and matching those to the ISO 26262 requirements (see e.g. for example :need:`PROCESS_gd_req__sm_doc_status`). @@ -310,7 +310,7 @@ Functional Safety Management SW Platform Work Products - not open sourced - to be shown to assessor - * - :need:`PROCESS_wp__qms` + * - :need:`PROCESS_wp__qms_plan` - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` - `#316 <https://github.com/eclipse-score/score/issues/316>`_ From 1d275b49636b3e4a46fb94081efa70f5e4b5bac5 Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 17 Jun 2025 17:01:44 +0200 Subject: [PATCH 048/102] process: typo corrected Ref: closes #316 --- docs/platform_management_plan/change_management.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/platform_management_plan/change_management.rst b/docs/platform_management_plan/change_management.rst index 7021c03397..15a508582c 100644 --- a/docs/platform_management_plan/change_management.rst +++ b/docs/platform_management_plan/change_management.rst @@ -217,7 +217,7 @@ ISSUE status ``OPEN`` and PR status ``OPEN``. if the Change Request is accepted or rejected. :need:`Committer <PROCESS_rl__committer>` checks finally if the Change Request is completed and the -required verification measures are executed and sucessfully passed. +required verification measures are executed and successfully passed. If ``approved``, the status of the concerned PRs change to ``MERGED``, otherwise, if rejected, PR status changes to ``CLOSED``. From 243e18701ba6d3bf2080fb6f187859bf8877d922 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> Date: Wed, 18 Jun 2025 13:18:46 +0200 Subject: [PATCH 049/102] updated directory structure moved design up one layer --- .../score-diagnostics-distributed.drawio.svg | 3 +- .../_assets/score-diagnostics.drawio.svg | 0 docs/features/diagnostics/design/index.rst | 299 ------------------ docs/features/diagnostics/index.rst | 292 ++++++++++++++++- .../diagnostics/requirements/index.rst | 1 + 5 files changed, 291 insertions(+), 304 deletions(-) rename docs/features/diagnostics/{design => }/_assets/score-diagnostics-distributed.drawio.svg (97%) rename docs/features/diagnostics/{design => }/_assets/score-diagnostics.drawio.svg (100%) delete mode 100644 docs/features/diagnostics/design/index.rst diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg similarity index 97% rename from docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg rename to docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg index e3e334625f..4e97cc08a3 100644 --- a/docs/features/diagnostics/design/_assets/score-diagnostics-distributed.drawio.svg +++ b/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg @@ -1,5 +1,6 @@ -<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1101px" height="762px" viewBox="-0.5 -0.5 1101 762" content="<mxfile scale="1" border="5"><diagram id="OtiXRZHrsBmRRigScPVE" name="Page-1">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</diagram></mxfile>"> +<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: #ffffff; background-color: light-dark(#ffffff, #121212);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1101px" height="762px" viewBox="-0.5 -0.5 1101 762" content="<mxfile scale="1" border="5"><diagram id="OtiXRZHrsBmRRigScPVE" name="Page-1">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</diagram></mxfile>"> <defs/> + <rect fill="#ffffff" width="100%" height="100%" x="0" y="0" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/> <g> <g> <path d="M 5 79 L 5 56 L 565 56 L 565 79" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/> diff --git a/docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics.drawio.svg similarity index 100% rename from docs/features/diagnostics/design/_assets/score-diagnostics.drawio.svg rename to docs/features/diagnostics/_assets/score-diagnostics.drawio.svg diff --git a/docs/features/diagnostics/design/index.rst b/docs/features/diagnostics/design/index.rst deleted file mode 100644 index 8f2236980d..0000000000 --- a/docs/features/diagnostics/design/index.rst +++ /dev/null @@ -1,299 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2025 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _diagnostics_feature: - -Diagnostic and Fault Management -############################### - -.. document:: Diagnostics - :id: doc__diagnostics - :status: draft - :safety: QM - :tags: feature_request - - -Feature flag -============ - -To activate this feature, use the following feature flag: - -``experimental_diagnostics`` - - -Abstract -======== - -We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. -SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, -eliminating the need for manually modeling diagnostic interfaces as required in UDS. -This significantly reduces integration overhead and simplifies the onboarding of new ECUs. -Additionally, SOVD enables scalable, secure, and cloud-ready diagnostics with real-time fault access and -advanced data handling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, -improve system maintainability, and support future-proof diagnostic workflows. - -The intent of this feature request is to define a high-level architecture for the diagnostic system. -The components listed throughout this document require detailed feature requests in the future respectively. - - -Motivation -========== - -Currently there is no solution for vehicle diagnostics in S-CORE. -Diagnostic is a core capability of automotive platform stacks and is required for various use-cases -such as field troubleshooting, quality assurance, after sales, production, development and more. - - -Rationale -========= - -SOVD was chosen as the foundation for the diagnostic architecture because it offers a modern, -service-oriented approach that aligns with the industry's shift toward Ethernet-based communication and scalable software-defined vehicle platforms. -It provides a standardized and extensible interface that enables better interoperability across ECUs, testers, and external tools. - - -Specification -============= - - -Architecture ------------- - -The proposed concept consists of three main parts: - -1. A framework agnostic library to aggregate faults and integrate the diagnostic system into S-CORE -2. A SOVD based diagnostic system -3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs - -The diagram below shows the concept with the three subgroups connected. - -.. image:: _assets/score-diagnostics.drawio.svg - :alt: Diagnostic stack component architecture - - -The next diagram shows the concept in a distributed view to highlight components that are unique per system or per device. - -.. image:: _assets/score-diagnostics-distributed.drawio.svg - :alt: Diagnostic stack component architecture - -In scope components -------------------- - -The following components are considered in scope of this feature request. - -Fault Library - -- Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. -- Relays faults via IPC to central Diagnostic Fault Manager. -- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface -- Reporting of faults additionally results in a log entry. -- The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. -- Fault lib is the base for activity specific, custom fault handling. -- Can and should also be used by platform components to report faults. -- Decentral component. - -Diagnostic Fault Manager - -- Aggregates and manages diagnostic fault data from Fault libs across the system. -- Provides centralized fault status to the SOVD Server. -- Interfaces with the Diagnostic DB (persistency) to store and retrieve data. -- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. -- Central component. - -Diagnostic DB - -- Stores static and runtime diagnostic data -- Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. -- The data format needs to be specified further but will likely include: -- Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. -- Fault ID (FID): ECU specific ID to uniquely identify every fault. -- Count: occurrence count of DTC/fault. -- Meta data: meta data related to fault occurrence. -- Central component. - -SOVD Server - -- Central entry point for all diagnostic requests via SOVD. -- Implements the SOVD API and dispatches requests to services, DB, and fault manager. -- Manages authentication, configuration, and data access via IPC. -- Central component. - -Service App - -- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). -- Interfaces with the SOVD Server via IPC. -- Central component derived from base service app. - -SOVD Gateway - -- Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). -- Acts as a router between clients and distributed SOVD components. -- Supports multi-ECU SOVD communication. -- Central component and unique per system. - -SOVD Client - -- Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. -- Can be used by developers, testers, ECUs or cloud services; should be deployment agnostic. -- Handles access control on the client side – e.g. by providing relevant certificates. -- Central component - but could be deployed mutliple times (e.g. one on-baord and one off-baord). - -Classic Diagnostic Adapter - -- Translates SOVD service calls to UDS commands. -- Enables backward compatibility with legacy ECUs that only support UDS. -- Configured via ODX files describing ECU-specific UDS expectations. -- Central component and unique per system. - -UDS2SOVD Proxy - -- Exposes selected SOVD functionality via UDS for backward-compatible testers. -- Acts as a local translation layer between UDS clients and SOVD stack. -- Configured via ODX files to define what is exposed. -- Central component and unique per system. - - -Out of scope components ------------------------ - -The following components are out of scope for this feature request but are included for context. -Each one is briefly described to illustrate its role within the overall system architecture and -to highlight any resulting requirements or constraints imposed by the diagnostic system design. - -Logging - -- Enables the Fault Library to log fault events. -- All SOVD components can interact with logging. - -Configuration Manager - -- Provides configuration data to the SOVD Server (e.g. ECU layout, variant, parameters). -- Enables parametrization of applications. - -Authentication Manager - -- Manages authentication and authorization for incoming SOVD requests. -- Ensures only valid users or clients can access services. - -Crypto - -- Provides cryptographic services – e.g. securely store and retrieve diagnostic certificates. -- Used by Authentication Manager. - -Persistency - -- Provides persistent data storage. - -Flash Service App - -- Specialized extension of the Service App to handle ECU flashing. -- Provides routines for software update/bootloader access via diagnostics. - -Rest of Vehicle UDS - -- Represents legacy ECUs in the vehicle that only speak UDS. -- Interact via the Classic Diagnostic Adapter (SOVD2UDS). - -Rest of Vehicle SOVD - -- Other ECUs in the vehicle that already support SOVD natively. -- Can communicate directly with the SOVD Gateway. - -UDS Tester - -- Traditional diagnostics tester that uses UDS protocol. -- Communicates with the UDS2SOVD Proxy for limited diagnostics access. - - -Requirements ------------- - -The related requirements can be found in :doc:`../requirements/index`. - - -Backwards Compatibility -======================= - -UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. -ODX as a standardized exchange format further ensures compatibility with proprietary diagnostic data models. - - -Security Impact -=============== - -The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. -Diagnostics inherently allow access to system information, state manipulation, coding, and software updates - all of which pose risks if accessed by unauthorized actors. -SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, -but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. -If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. -This may enable new threat scenarios and attack paths, particularly over external or less trusted networks. -To mitigate these risks, the diagnostic stack shall enforce secure communication via HTTPS, -authenticate endpoints using certificates (see architecture diagram), and implement strict access control mechanisms. -While diagnostics do not directly impact functional safety, a successful attack could indirectly influence safety-relevant functions -- for example by setting the system into a different state. -Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. - - -Safety Impact -============= - -At this point in time no direct safety impact is foreseen. The expected ASIL level is QM. -Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. -As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions -- for example by setting the system into a different state. - - -License Impact -============== - -There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. -While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts - especially Part 3, -which defines the API - are already publicly available for purchase as Draft International Standards (DIS). -These drafts are considered stable and are typically subject only to minor editorial changes before final publication. -As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. -Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. - -The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. - - -How to Teach This -================= - -A good starting point to get an overview of SOVD is the overview pages provided by ISO [#s1]_ and ASAM [#s2]_. - - -Rejected Ideas -============== - -An UDS first based diagnostic system was considered but rejected. -The current market trend clearly indicates the move towards SOVD. -Additionally, there a multiple well established proprietary UDS stacks and tools available. -Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CORE to provide value and increase adoption. - - -Open Issues -=========== - -- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase -- Investigate synergies between Configuration Manager and Diagnostic Fault Manager -- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 -- Check if Diagnostic Fault Manager component is required at all and could be removed (how would this impact dependency of Flib to persistency and access management?) -- Provide sequence diagram for a use case - - -Footnotes -========= - -.. [#s1] "SOVD Standard ISO/DIS 17978", ISO, https://www.iso.org/standard/85133.html. -.. [#s2] "ASAM SOVD Overview", ASAM, https://www.asam.net/standards/detail/sovd. diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index a3a5c61beb..b8d1f514ae 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -1,6 +1,6 @@ .. # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation + # Copyright (c) 2025 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,12 +12,296 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Diagnostics -########### +.. _diagnostics_feature: + +Diagnostic and Fault Management +############################### + +.. document:: Diagnostics + :id: doc__diagnostics + :status: draft + :safety: QM + :tags: feature_request + .. toctree:: :maxdepth: 1 :glob: :titlesonly: + :hidden: + + requirements/index + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_diagnostics`` + + +Abstract +======== + +We propose adding support for Vehicle Diagnostics via Service-Oriented Vehicle Diagnostics (SOVD) within S-CORE. +SOVD offers a service-oriented, self-descriptive interface based on standardized RESTful APIs, +eliminating the need for manually modeling diagnostic interfaces as required in UDS. +This significantly reduces integration overhead and simplifies the onboarding of new ECUs. +Additionally, SOVD enables scalable, secure, and cloud-ready diagnostics with real-time fault access and +advanced data handling across platforms. Integrating SOVD into S-CORE will enhance developer efficiency, +improve system maintainability, and support future-proof diagnostic workflows. + +The intent of this feature request is to define a high-level architecture for the diagnostic system. +The components listed throughout this document require detailed feature requests in the future respectively. + + +Motivation +========== + +Currently there is no solution for vehicle diagnostics in S-CORE. +Diagnostic is a core capability of automotive platform stacks and is required for various use-cases +such as field troubleshooting, quality assurance, after sales, production, development and more. + + +Rationale +========= + +SOVD was chosen as the foundation for the diagnostic architecture because it offers a modern, +service-oriented approach that aligns with the industry's shift toward Ethernet-based communication and scalable software-defined vehicle platforms. +It provides a standardized and extensible interface that enables better interoperability across ECUs, testers, and external tools. + + +Specification +============= + + +Architecture +------------ + +The proposed concept consists of three main parts: + +1. A framework agnostic library to aggregate faults and integrate the diagnostic system into S-CORE +2. A SOVD based diagnostic system +3. Components to interface the diagnostic system with the outside – e.g. Tester or UDS based ECUs + +The diagram below shows the concept with the three subgroups connected. + +.. image:: _assets/score-diagnostics.drawio.svg + :alt: Diagnostic stack component architecture + + +The next diagram shows the concept in a distributed view to highlight components that are unique per system or per device. + +.. image:: _assets/score-diagnostics-distributed.drawio.svg + :alt: Diagnostic stack component architecture + +In scope components +------------------- + +The following components are considered in scope of this feature request. + +Fault Library + +- Provides a framework agnostic interface for apps or FEO activities to report faults - called "Fault API" in the S-CORE architecture. +- Relays faults via IPC to central Diagnostic Fault Manager. +- Enables domain-specific error logic (e.g. debouncing) by exposing a configuration interface +- Reporting of faults additionally results in a log entry. +- The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. +- Fault lib is the base for activity specific, custom fault handling. +- Can and should also be used by platform components to report faults. +- Decentral component. + +Diagnostic Fault Manager + +- Aggregates and manages diagnostic fault data from Fault libs across the system. +- Provides centralized fault status to the SOVD Server. +- Interfaces with the Diagnostic DB (persistency) to store and retrieve data. +- Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. +- Central component. + +Diagnostic DB + +- Stores static and runtime diagnostic data +- Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. +- The data format needs to be specified further but will likely include: +- Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. +- Fault ID (FID): ECU specific ID to uniquely identify every fault. +- Count: occurrence count of DTC/fault. +- Meta data: meta data related to fault occurrence. +- Central component. + +SOVD Server + +- Central entry point for all diagnostic requests via SOVD. +- Implements the SOVD API and dispatches requests to services, DB, and fault manager. +- Manages authentication, configuration, and data access via IPC. +- Central component. + +Service App + +- Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). +- Interfaces with the SOVD Server via IPC. +- Central component derived from base service app. + +SOVD Gateway + +- Forwards SOVD requests to appropriate backend targets (e.g. adapters, proxies, clients). +- Acts as a router between clients and distributed SOVD components. +- Supports multi-ECU SOVD communication. +- Central component and unique per system. + +SOVD Client + +- Off-board, on-board or cloud client that initiates diagnostics via SOVD protocol. +- Can be used by developers, testers, ECUs or cloud services; should be deployment agnostic. +- Handles access control on the client side – e.g. by providing relevant certificates. +- Central component - but could be deployed mutliple times (e.g. one on-baord and one off-baord). + +Classic Diagnostic Adapter + +- Translates SOVD service calls to UDS commands. +- Enables backward compatibility with legacy ECUs that only support UDS. +- Configured via ODX files describing ECU-specific UDS expectations. +- Central component and unique per system. + +UDS2SOVD Proxy + +- Exposes selected SOVD functionality via UDS for backward-compatible testers. +- Acts as a local translation layer between UDS clients and SOVD stack. +- Configured via ODX files to define what is exposed. +- Central component and unique per system. + + +Out of scope components +----------------------- + +The following components are out of scope for this feature request but are included for context. +Each one is briefly described to illustrate its role within the overall system architecture and +to highlight any resulting requirements or constraints imposed by the diagnostic system design. + +Logging + +- Enables the Fault Library to log fault events. +- All SOVD components can interact with logging. + +Configuration Manager + +- Provides configuration data to the SOVD Server (e.g. ECU layout, variant, parameters). +- Enables parametrization of applications. + +Authentication Manager + +- Manages authentication and authorization for incoming SOVD requests. +- Ensures only valid users or clients can access services. + +Crypto + +- Provides cryptographic services – e.g. securely store and retrieve diagnostic certificates. +- Used by Authentication Manager. + +Persistency + +- Provides persistent data storage. + +Flash Service App + +- Specialized extension of the Service App to handle ECU flashing. +- Provides routines for software update/bootloader access via diagnostics. + +Rest of Vehicle UDS + +- Represents legacy ECUs in the vehicle that only speak UDS. +- Interact via the Classic Diagnostic Adapter (SOVD2UDS). + +Rest of Vehicle SOVD + +- Other ECUs in the vehicle that already support SOVD natively. +- Can communicate directly with the SOVD Gateway. + +UDS Tester + +- Traditional diagnostics tester that uses UDS protocol. +- Communicates with the UDS2SOVD Proxy for limited diagnostics access. + + +Requirements +------------ + +The related requirements can be found in :doc:`requirements/index`. + + +Backwards Compatibility +======================= + +UDS2SOVD Proxy and Classic Diagnostic Adapter (SOVD2UDS) ensure compatibility with legacy UDS systems. +ODX as a standardized exchange format further ensures compatibility with proprietary diagnostic data models. + + +Security Impact +=============== + +The introduction of a SOVD based diagnostic stack has significant security implications due to its capabilities and network-based communication model. +Diagnostics inherently allow access to system information, state manipulation, coding, and software updates - all of which pose risks if accessed by unauthorized actors. +SOVD, based on REST, includes modern security features such as HTTPS and token-based authentication, +but also introduces a broader attack surface compared to traditional UDS, which relies on more isolated, session-based access. +If improperly secured, diagnostic interfaces could be exploited to trigger unauthorized routines or inject malicious software. +This may enable new threat scenarios and attack paths, particularly over external or less trusted networks. +To mitigate these risks, the diagnostic stack shall enforce secure communication via HTTPS, +authenticate endpoints using certificates (see architecture diagram), and implement strict access control mechanisms. +While diagnostics do not directly impact functional safety, a successful attack could indirectly influence safety-relevant functions +- for example by setting the system into a different state. +Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. + + +Safety Impact +============= + +At this point in time no direct safety impact is foreseen. The expected ASIL level is QM. +Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. +As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions +- for example by setting the system into a different state. + + +License Impact +============== + +There are no license restrictions preventing the implementation of an open-source SOVD stack at this time. +While SOVD is currently in the ISO standardization process (ISO/DIS 17978) [#s1]_, the relevant parts - especially Part 3, +which defines the API - are already publicly available for purchase as Draft International Standards (DIS). +These drafts are considered stable and are typically subject only to minor editorial changes before final publication. +As such, referencing the current DIS versions is sufficient for implementation purposes, and does not pose any legal or license-related risk. +Once the final ISO standard is published, the delta to the current drafts is expected to be minimal and can be easily addressed. + +The license impact regarding publication of XML schemata to handle/convert ODX files as per ISO 22901 needs to be evaluated. + + +How to Teach This +================= + +A good starting point to get an overview of SOVD is the overview pages provided by ISO [#s1]_ and ASAM [#s2]_. + + +Rejected Ideas +============== + +An UDS first based diagnostic system was considered but rejected. +The current market trend clearly indicates the move towards SOVD. +Additionally, there a multiple well established proprietary UDS stacks and tools available. +Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CORE to provide value and increase adoption. + + +Open Issues +=========== + +- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase +- Investigate synergies between Configuration Manager and Diagnostic Fault Manager +- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 +- Check if Diagnostic Fault Manager component is required at all and could be removed (how would this impact dependency of Flib to persistency and access management?) +- Provide sequence diagram for a use case + + +Footnotes +========= - */index +.. [#s1] "SOVD Standard ISO/DIS 17978", ISO, https://www.iso.org/standard/85133.html. +.. [#s2] "ASAM SOVD Overview", ASAM, https://www.asam.net/standards/detail/sovd. diff --git a/docs/features/diagnostics/requirements/index.rst b/docs/features/diagnostics/requirements/index.rst index 8f12672900..6c1d5055be 100644 --- a/docs/features/diagnostics/requirements/index.rst +++ b/docs/features/diagnostics/requirements/index.rst @@ -12,6 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +.. _diagnostics_requirements: Requirements ############ From cf84d00b6ba2ff86016c6808a1f95b0345fcace1 Mon Sep 17 00:00:00 2001 From: Markus Schu <142009492+masc2023@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:45:36 +0200 Subject: [PATCH 050/102] update process_description version (#1259) --- MODULE.bazel | 2 +- docs/platform_management_plan/safety_management.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index bf6d0c3344..540c795be4 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -91,4 +91,4 @@ bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs bazel_dep(name = "score_docs_as_code", version = "0.3.3") -bazel_dep(name = "score_process", version = "0.2.0") +bazel_dep(name = "score_process", version = "1.0.1") diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index b915c3ed6a..ad213bf5fe 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -310,7 +310,7 @@ Functional Safety Management SW Platform Work Products - not open sourced - to be shown to assessor - * - :need:`PROCESS_wp__qms` + * - :need:`PROCESS_wp__qms_plan` - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` - `#316 <https://github.com/eclipse-score/score/issues/316>`_ From 9b50e2f3c781e495bb8c7beeb5af3fd6429bcd50 Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 17 Jun 2025 17:46:20 +0200 Subject: [PATCH 051/102] process: include review findings Ref: closes#316 process: include review findings. update module.bazel Ref: closes #316 process: include review findings continue work in issue 1264 Ref: closes #316 --- MODULE.bazel | 4 +- .../quality_management.rst | 39 ++++++++----------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index bf6d0c3344..56e4ad9214 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -13,7 +13,7 @@ module( name = "score_platform", - version = "0.2.0", + version = "1.0.1", compatibility_level = 0, ) @@ -91,4 +91,4 @@ bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs bazel_dep(name = "score_docs_as_code", version = "0.3.3") -bazel_dep(name = "score_process", version = "0.2.0") +bazel_dep(name = "score_process", version = "1.0.1") diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index 5ecb7d10f8..fc2728a648 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -19,6 +19,7 @@ Quality Management / Platform Quality Management Plan :id: doc__platform_quality_plan :status: valid :safety: ASIL_B + :security: YES :realizes: PROCESS_wp__qms_plan :tags: platform_management @@ -45,8 +46,8 @@ the :need:`PROCESS_rl__quality_manager` is independent of the delivery of the pr :alt: Project Organization :align: center -In SCORE we have different Tier and OEM stakeholder involved: Every solution will be checked by the other stakeholders. -This is another strong independent mechanism to ensure Quality. +In S-CORE we have different Tier and OEM stakeholder involved: Every solution will be checked by the other stakeholders. +This is another strong independent mechanism to ensure quality. Objectives and scope -------------------- @@ -91,7 +92,7 @@ Objectives and scope - Feature process conformance checks - Once for every feature release * - 3 - - Feature work product review + - Work product review - Once for every feature release * - 4 - Platform release verification and approval @@ -121,7 +122,7 @@ Objectives and scope - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` - 100% of the Platform process audit has be done for every release - Delta audit allowed to achieve 100% - - Ensured by the process process management, :need:`PROCESS_wp__process_impr_report` - Platform process audit is available + - Ensured by the process quality management, :need:`PROCESS_wf__exe_pltprocess_audit` - Platform process audit is available * - 2 - One process conformance check for every feature release - :need:`stkh_req__dependability__automotive_safety`, :doc:`../requirements/stakeholder/index` @@ -235,17 +236,16 @@ the (Eclipse) committer role. As defined in `Committer Training <https://www.ecl committers are elected in a meritrocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. -As each project can adopt additional criteria for the committers election, S-Core defines that each committer has to prove +As each project can adopt additional criteria for the committers election, S-CORE defines that each committer has to prove his knowledge in quality SW development by: - by attending the project's ASPICE 4.0 SW management and development training. -Additionally, the project repository is organized in "CODEOWNER" sections. These "CODEOWNERS" need to approve any pull -request modifying a file in their area of responsibility before it gets merged. In case of quality related "CODEOWNER" sections (e.g. -any documentation artefacts) the persons having "CODEOWNER" rights need to be qualified according to the roles description -Quality Manager :need:`PROCESS_rl__quality_manager`. +Additionally, the project repository shall be organized in a way that independent roles (to the technical solution) + have to approve any pull request before it's merged. The persons who are able to approve need to be qualified + according to the roles description Quality Manager :need:`PROCESS_rl__quality_manager`. -The successful checking of committers and CODEOWNERS skills is ensured by the Project and Quality Manager :need:`PROCESS_rl__quality_manager` and documented +The successful checking of the skills of the committers and independent roles is ensured by the Project and Quality Manager :need:`PROCESS_rl__quality_manager` and documented in the role assignment document. .. note:: The identity of the committer by applying the GitHub digital signature mechanism will be used to confirm the authenticity of the Quality Manager :need:`PROCESS_rl__quality_manager` role for the approvals @@ -291,7 +291,7 @@ The quality management status :need:`PROCESS_wp__qms_report` is reported as defi **Examples for valid escalation causes are:** - Quality issues cannot be resolved on feature level or with the available resources. -- There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Safety Manager :need:`PROCESS_rl__safety_manager`, Security Manager :need:`PROCESS_rl__security_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` +- There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Technical Lead :need:`PROCESS_rl__technical_lead`, Safety Manager :need:`PROCESS_rl__safety_manager`, Security Manager :need:`PROCESS_rl__security_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` 4.3 Quality Management Specifics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +313,7 @@ None - :need:`PROCESS_gd_guidl__saf_plan_definitions` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` - `#470 <https://github.com/eclipse-score/score/issues/470>`_ - - <Link to WP> + - :need:`doc__platform_change_management_plan` - <automated> * - :need:`PROCESS_wp__chm_plan` @@ -341,7 +341,7 @@ None - :need:`PROCESS_gd_guidl__documentation` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__documentation')` - <Link to issue> - - <Link to WP> + - :need:`doc__documentation_mgt_plan` - <automated> * - :need:`PROCESS_wp__fdr_reports` @@ -355,7 +355,7 @@ None - :need:`PROCESS_gd_guidl__change__change_request` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` - <Link to issue> - - <Link to WP> + - :need:`doc__logging`, :need:`doc__com`, :need:`doc__feo`, :need:`doc__persistency_kvs` - <automated> * - :need:`PROCESS_wp__feature_arch` @@ -386,13 +386,6 @@ None - <Link to WP> - <automated> - * - :need:`PROCESS_wp__issue_track_system` - - :need:`PROCESS_gd_guidl__change__change_request` - - :ndf:`copy('status', need_id='PROCESS_gd_guidl__change__change_request')` - - <Link to issue> - - <Link to WP> - - <automated> - * - :need:`PROCESS_wp__module_safety_manual` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` @@ -523,7 +516,7 @@ None - :need:`PROCESS_gd_guidl__qlm_plan_definitions` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__qlm_plan_definitions')` - <Link to issue> - - <Link to WP> + - :need:`doc__platform_quality_plan` - <automated> * - :need:`PROCESS_wp__qms_report` @@ -635,7 +628,7 @@ None - :need:`PROCESS_doc_concept__tool__process` - :ndf:`copy('status', need_id='PROCESS_doc_concept__tool__process')` - <Link to issue> - - <Link to WP> + - :need:`doc__platform_tool_management_plan` - <automated> * - :need:`PROCESS_wp__tool_verification_report` From acd76f7dedd5f5e6ab1b5a88aa3feae5698df38a Mon Sep 17 00:00:00 2001 From: Markus Hosch <markus.hosch@bmw.de> Date: Tue, 24 Jun 2025 14:13:23 +0200 Subject: [PATCH 052/102] Add guideline on how to design Rust APIs in S-Core Add a document that outlines how Rust APIs should look like. The current chapter focuses on testability by requiring a trait for public APIs so that using system parts may receive mocks to be able to test them. --- docs/contribute/development/rust/index.rst | 1 + .../development/rust/rust_api_design.rst | 243 ++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 docs/contribute/development/rust/rust_api_design.rst diff --git a/docs/contribute/development/rust/index.rst b/docs/contribute/development/rust/index.rst index b0fb6a40ed..4038278ae5 100644 --- a/docs/contribute/development/rust/index.rst +++ b/docs/contribute/development/rust/index.rst @@ -19,3 +19,4 @@ Rust :maxdepth: 1 coding_guidelines + rust_api_design diff --git a/docs/contribute/development/rust/rust_api_design.rst b/docs/contribute/development/rust/rust_api_design.rst new file mode 100644 index 0000000000..ab5a8cbe1e --- /dev/null +++ b/docs/contribute/development/rust/rust_api_design.rst @@ -0,0 +1,243 @@ +Rust API design guidelines +########################## + +.. document:: Rust API design guidelines + :id: doc__rust_api_design + :status: draft + +Preface +======= + +This document describes how public Rust APIs shall be designed in the S-CORE context. While these guidelines canalso be +beneficial for private APIs, following them also inside a single module is reommended to improve the code consistency +and also benefit from the perks it gives to the code. + +Writing Mockable Rust Code +========================== + +Mockable Rust code is a design pattern that emphasizes testability by expressing public APIs in terms of traits. This +approach allows developers to swap out real implementations with mock implementations during testing, enabling +controlled and predictable behavior for unit tests. By adhering to this pattern, you can isolate components under test +and avoid dependencies on external systems or complex logic. + +Why Traits Enable Mocking +------------------------- + +In Rust, traits define shared behavior that can be implemented by multiple types. When public APIs are expressed as +traits, you can provide one implementation for the real use case and another for testing purposes. During testing, a +mock struct (often created using crates like ``mockall``) can simulate the behavior of the real implementation, allowing +you to test your code in isolation. The mock struct may also be provided by the provider of the API so that users do not +need to reinvent the wheel by providing yet another mock implementation. + +Below you will find an example of naive coding that is difficult to test because it directly depends on a concrete +implementation: + +.. code-block:: rust + + pub struct RealDataFetcher; + + impl RealDataFetcher { + pub fn fetch_data(&self, key: &str) -> String { + format!("Real data for key: {}", key) + } + } + + pub struct DataProcessor { + fetcher: RealDataFetcher, + } + + impl DataProcessor { + pub fn new(fetcher: RealDataFetcher) -> Self { + Self { fetcher } + } + + pub fn process(&self, key: &str) -> String { + let data = self.fetcher.fetch_data(key); + format!("Processed: {}", data) + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn test_data_processor() { + let fetcher = RealDataFetcher; + let processor = DataProcessor::new(fetcher); + + let result = processor.process("test_key"); + + assert_eq!(result, "Processed: Real data for key: test_key"); + } + } + +The ``DataProcessor`` directly depends on ``RealDataFetcher``, making it impossible to substitute a mock implementation. +Tests cannot control or predict the behavior of ``fetch_data``, leading to reliance on real data or external systems. +This coupling makes the code harder to test and less flexible. + +The solution to these issues is a refactoring that extracts the API from teh implementation by means of a trait and using +a system part by means of that trait instead of a direct dependency, as above. + +Providing the implementation for this trait can be done in two different ways in Rust: Static dispatch by means of generic +parameters or dynamic dispatch by handing over references to trait objects. The following paragraphs will give examples +for both methods. + +Positive Example: Mockable Code with Static Dispatch +---------------------------------------------------- + +Below is an example of mockable Rust code using the ``mockall`` crate and static dispatch: + +.. code-block:: rust + + pub trait DataFetcher { + fn fetch_data(&self, key: &str) -> String; + } + + pub struct RealDataFetcher; + + impl DataFetcher for RealDataFetcher { + fn fetch_data(&self, key: &str) -> String { + format!("Real data for key: {}", key) + } + } + + pub struct DataProcessor<T: DataFetcher> { + fetcher: T, + } + + impl<T: DataFetcher> DataProcessor<T> { + pub fn new(fetcher: T) -> Self { + Self { fetcher } + } + + pub fn process(&self, key: &str) -> String { + let data = self.fetcher.fetch_data(key); + format!("Processed: {}", data) + } + } + + #[cfg(test)] + mockall::mock! { + pub DataFetcher {} + + impl DataFetcher for DataFetcher { + fn fetch_data(&self, key: &str) -> String; + } + } + + #[cfg(test)] + mod tests { + use super::*; + use mockall::predicate::*; + + #[test] + fn test_data_processor_with_mock() { + let mut mock_fetcher = MockDataFetcher::new(); + mock_fetcher + .expect_fetch_data() + .with(eq("test_key")) + .returning(|_| "Mock data".to_string()); + + let processor = DataProcessor::new(mock_fetcher); + let result = processor.process("test_key"); + + assert_eq!(result, "Processed: Mock data"); + } + } + +Positive Example: Mockable Code with Dynamic Dispatch +----------------------------------------------------- + +Here’s an example using dynamic dispatch with a ``&mut dyn`` reference: + +.. code-block:: rust + + #[cfg_attr(test, mockall::automock)] + pub trait DataFetcher { + fn fetch_data(&self, key: &str) -> String; + } + + pub struct RealDataFetcher; + + impl DataFetcher for RealDataFetcher { + fn fetch_data(&self, key: &str) -> String { + format!("Real data for key: {}", key) + } + } + + pub struct DataProcessor<'a> { + fetcher: &'a mut dyn DataFetcher, + } + + impl<'a> DataProcessor<'a> { + pub fn new(fetcher: &'a mut dyn DataFetcher) -> Self { + Self { fetcher } + } + + pub fn process(&self, key: &str) -> String { + let data = self.fetcher.fetch_data(key); + format!("Processed: {}", data) + } + } + + #[cfg(test)] + mod tests { + use super::*; + use mockall::predicate::*; + + #[test] + fn test_data_processor_with_dyn_dispatch() { + let mut mock_fetcher = MockDataFetcher::new(); + mock_fetcher + .expect_fetch_data() + .with(eq("test_key")) + .returning(|_| "Mock data".to_string()); + + let processor = DataProcessor::new(&mut mock_fetcher); + let result = processor.process("test_key"); + + assert_eq!(result, "Processed: Mock data"); + } + } + + +.. note:: Instead of explicitly implementing the mock as in the above example, we now use ``automock`` to generate the + mock implementation. While this isn't always possible, it is very convenient in most cases where the macro + works. + +Pros and Cons of Static vs Dynamic Dispatch +------------------------------------------- + +**Static Dispatch:** + +* **Pros:** + + * Compile-time type checking ensures safety and performance. + * No runtime overhead for method calls. + * Easier to optimize by the compiler. + +* **Cons:** + + * Requires generics, which can increase code complexity and binary size. + * May lead to code duplication if many types implement the same trait. + +**Dynamic Dispatch:** + +* **Pros:** + + * Allows runtime polymorphism, making the code more flexible. + * Avoids generics, reducing code complexity and binary size. + +* **Cons:** + + * Slight runtime overhead due to vtable lookups. + * Less compile-time type safety compared to static dispatch. + +Conclusion +---------- + +By designing APIs around traits, you can create mockable Rust code that is easier to test and maintain. Both static and +dynamic dispatch have their use cases, and the choice depends on the specific requirements of your project. Static +dispatch is ideal for performance-critical applications, while dynamic dispatch offers flexibility and simplicity. Avoid +direct dependencies on concrete implementations to prevent testing difficulties and tightly coupled code. From 3bfec77da85727b00693b8c01bc37efd8e87dbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20H=C3=A4ussler?= <volker.haeussler@qorix.ai> Date: Wed, 11 Jun 2025 08:21:47 +0200 Subject: [PATCH 053/102] process: initial summary of Rust coding guidelines Ref: closes #1085 --- .../development/rust/coding_guidelines.rst | 50 ++++++++++++++++++- .../software_development.rst | 2 +- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/docs/contribute/development/rust/coding_guidelines.rst b/docs/contribute/development/rust/coding_guidelines.rst index 1ce642536b..288f652806 100644 --- a/docs/contribute/development/rust/coding_guidelines.rst +++ b/docs/contribute/development/rust/coding_guidelines.rst @@ -17,6 +17,52 @@ Writing Rust Code .. document:: Coding Guidelines Rust :id: doc__rust_coding_guidelines - :status: invalid + :status: valid -.. note:: The Rust coding guidelines are not yet defined. This is a placeholder for future content. +Coding Guidelines +################# + +The Rust consortium has decided that there will be no official coding guidelines provided by the Rust consortium. +However, the Rust community has a set of guidelines that are widely accepted and used. +These guidelines can be found in the official Rust documentation and are recommended for all Rust projects. + +`Safety Critical Rust Consortium <https://github.com/rustfoundation/safety-critical-rust-consortium/tree/main/subcommittee/coding-guidelines/>`_ + +`Learn unsafe Rust <https://google.github.io/learn_unsafe_rust/>`_ + +`Rust language <https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html>`_ + +State of Rust Safety-Critical Tooling +##################################### + +An actual state of Rust safety critical tooling can be found in the following document: + +`Mission statement Rust safety critical tooling <https://github.com/rustfoundation/safety-critical-rust-consortium/blob/main/subcommittee/tooling/mission-statement.md>`_ + + +Explanation of ARA Applications in Rust +####################################### + +Autosar also shares a public availabe document that explains how to use Rust in ARA applications. + +`Autosar Rust ARA applications <https://www.autosar.org/fileadmin/standards/R24-11/AP/AUTOSAR_AP_EXP_ARARustApplications.pdf>`_ + + +MISRA vs Cert +############# + +`MISRA vs Cert <https://github.com/rustfoundation/safety-critical-rust-coding-guidelines/issues/75/>`_ + +Link to Clippy +############## + +`Link to Clippy <https://github.com/rustfoundation/safety-critical-rust-coding-guidelines/issues/78/>`_ + + +Conclusions for S-CORE +###################### + +During the S-CORE project, we will not enforce any coding guidelines for Rust. +However, we will follow the guidelines provided by the Rust community and the Rust consortium. +We will also follow the guidelines provided by the Rust Foundation and the Safety Critical Rust Consortium. +The adaption of these guidelines will be documented in the S-CORE project documentation. diff --git a/docs/platform_management_plan/software_development.rst b/docs/platform_management_plan/software_development.rst index b72128b61f..1fc54164ad 100644 --- a/docs/platform_management_plan/software_development.rst +++ b/docs/platform_management_plan/software_development.rst @@ -72,7 +72,7 @@ Coding guideline **C++** - see :need:`doc__cpp_coding_guidelines` **Rust** - state of the art open source Rust guidelines are currently developed by `Safety Critical Rust Consortium <https://github.com/rustfoundation/safety-critical-rust-consortium/>`_ -(which will be adopted by the S-CORE project) +(which will be adopted by the S-CORE project). A summary of the current state of informations regarding Rust in safety critical applications can be found in :need:`doc__rust_coding_guidelines`. SW configuration guideline ^^^^^^^^^^^^^^^^^^^^^^^^^^ From d85b4c26a5109ecffb396c6be4df0950df3be96e Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 10 Jun 2025 18:49:05 +0200 Subject: [PATCH 054/102] process: small format changes Ref: closes #1085 --- docs/contribute/development/rust/coding_guidelines.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contribute/development/rust/coding_guidelines.rst b/docs/contribute/development/rust/coding_guidelines.rst index 288f652806..ed01c1c8e0 100644 --- a/docs/contribute/development/rust/coding_guidelines.rst +++ b/docs/contribute/development/rust/coding_guidelines.rst @@ -20,7 +20,7 @@ Writing Rust Code :status: valid Coding Guidelines -################# +================= The Rust consortium has decided that there will be no official coding guidelines provided by the Rust consortium. However, the Rust community has a set of guidelines that are widely accepted and used. From 2e023e4ba9cf3a282fc5ef536b320427552fc4fa Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 11 Jun 2025 12:31:08 +0200 Subject: [PATCH 055/102] process: Rust guideline-following adapted Ref: closes #1085 --- .../development/rust/coding_guidelines.rst | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/contribute/development/rust/coding_guidelines.rst b/docs/contribute/development/rust/coding_guidelines.rst index ed01c1c8e0..2ad17a4f84 100644 --- a/docs/contribute/development/rust/coding_guidelines.rst +++ b/docs/contribute/development/rust/coding_guidelines.rst @@ -22,11 +22,13 @@ Writing Rust Code Coding Guidelines ================= -The Rust consortium has decided that there will be no official coding guidelines provided by the Rust consortium. -However, the Rust community has a set of guidelines that are widely accepted and used. -These guidelines can be found in the official Rust documentation and are recommended for all Rust projects. +The Safety-Critical Rust Consortium plans to develop guidelines, linters, +libraries, static analysis tools, formal methods and language subsets to meet +industrial and legal requirements. -`Safety Critical Rust Consortium <https://github.com/rustfoundation/safety-critical-rust-consortium/tree/main/subcommittee/coding-guidelines/>`_ +`Safety-Critical Rust Consortium <https://rustfoundation.org/safety-critical-rust-consortium>`_ + +`Safety-Critical Rust Consortium Guidelines <https://github.com/rustfoundation/safety-critical-rust-consortium/tree/main/subcommittee/coding-guidelines/>`_ `Learn unsafe Rust <https://google.github.io/learn_unsafe_rust/>`_ @@ -62,7 +64,12 @@ Link to Clippy Conclusions for S-CORE ###################### -During the S-CORE project, we will not enforce any coding guidelines for Rust. -However, we will follow the guidelines provided by the Rust community and the Rust consortium. -We will also follow the guidelines provided by the Rust Foundation and the Safety Critical Rust Consortium. -The adaption of these guidelines will be documented in the S-CORE project documentation. +During the S-CORE project only formatting and clippy checks are enforced. Also +the code should compile with zero warnings. Additional guidelines by the Rust +Community, the Rust Foundation and the Safety-Critical Rust Consortium are +applied where applicable but not enforced. If possible the usage of `unsafe` is +avoided. To keep the code `panic`-free only APIs with a proper return value +should be used. + +The adaption of these guidelines will be documented in the S-CORE project +documentation. From 45f2286f2009cc35e75df499a8878c1d74a4171e Mon Sep 17 00:00:00 2001 From: Sven Bachmann <sven.bachmann.ext@qorix.ai> Date: Wed, 11 Jun 2025 12:43:29 +0200 Subject: [PATCH 056/102] process: enrich each Rust guideline section with an explanation Ref: closes #1085 --- .../development/rust/coding_guidelines.rst | 59 ++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/docs/contribute/development/rust/coding_guidelines.rst b/docs/contribute/development/rust/coding_guidelines.rst index 2ad17a4f84..e9a6d5c70f 100644 --- a/docs/contribute/development/rust/coding_guidelines.rst +++ b/docs/contribute/development/rust/coding_guidelines.rst @@ -19,12 +19,23 @@ Writing Rust Code :id: doc__rust_coding_guidelines :status: valid + Coding Guidelines ================= -The Safety-Critical Rust Consortium plans to develop guidelines, linters, -libraries, static analysis tools, formal methods and language subsets to meet -industrial and legal requirements. +The Safety-Critical Rust Consortium aims to make Rust suitable for use in +automotive and other safety-critical environments by building and maintaining a +set of essential tools that are vetted by the community for certification +purposes. They track the development status of these tools and document their +progress. The consortium is considering whether to develop specialized training +materials for safety-critical Rust, though this may require a separate group. +Their current activities include supporting a qualified compiler (with +Ferrocene available for some targets), developing a certified core library, +working on tools for coding style verification, and assessing the need for +static analysis and code metrics tools. Some tools, such as MC/DC coverage +reporting and code metrics generators, are still unavailable, and the +consortium is evaluating what further tooling and support are necessary to +enable certification and safe use of Rust in automotive applications. `Safety-Critical Rust Consortium <https://rustfoundation.org/safety-critical-rust-consortium>`_ @@ -34,30 +45,64 @@ industrial and legal requirements. `Rust language <https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html>`_ + State of Rust Safety-Critical Tooling ##################################### -An actual state of Rust safety critical tooling can be found in the following document: +The linked document provides a current overview of the tooling landscape for +certifying Rust in safety-critical applications, presenting a +community-approved list of essential tools and tracking their development +status. It also explores whether developing specialized training curricula for +safety-critical Rust is necessary, potentially requiring a separate +subcommittee. The document details the state of specific tools—such as +compilers and analysis utilities—by outlining their intended purposes, +certification requirements, and their availability or progress. While some +tools, such as the Ferrocene compiler, are already available or being actively +developed, others remain under evaluation or are not yet accessible. -`Mission statement Rust safety critical tooling <https://github.com/rustfoundation/safety-critical-rust-consortium/blob/main/subcommittee/tooling/mission-statement.md>`_ +`Mission Statement - Tooling Subcommittee <https://github.com/rustfoundation/safety-critical-rust-consortium/blob/main/subcommittee/tooling/mission-statement.md>`_ Explanation of ARA Applications in Rust ####################################### -Autosar also shares a public availabe document that explains how to use Rust in ARA applications. +AUTOSAR also shares a public availabe document that explains how to use Rust in +ARA applications as Rust is offering safety and performance advantages. While +ecosystem support is still maturing, Rust-based ARA applications can lead to +safer, more reliable automotive software, especially in safety-critical and +high-performance domains. -`Autosar Rust ARA applications <https://www.autosar.org/fileadmin/standards/R24-11/AP/AUTOSAR_AP_EXP_ARARustApplications.pdf>`_ +`AUTOSAR ARA Applications in Rust <https://www.autosar.org/fileadmin/standards/R24-11/AP/AUTOSAR_AP_EXP_ARARustApplications.pdf>`_ MISRA vs Cert ############# +This issue contrasts the MISRA and CERT coding standards, highlighting their +different approaches to software safety and security. MISRA is noted for its +restrictive language subsetting and complex compliance process, often imposing +outdated or ineffective rules that do not guarantee improved safety or +security. This can create unnecessary work for developers without clear +benefits and is sometimes inconsistent across languages. CERT, on the other +hand, is praised for its focus on practical, consensus-based rules that target +real security vulnerabilities in existing code, avoiding excessive constraints. +The overall recommendation is to favor guidelines like CERT’s—practical, +evidence-based, and focused on real-world issues—over rigid, untested standards +that hinder adoption and developer productivity. + `MISRA vs Cert <https://github.com/rustfoundation/safety-critical-rust-coding-guidelines/issues/75/>`_ + Link to Clippy ############## +Rust Clippy is a collection of lints (code style and correctness checks) for +the Rust programming language. It helps developers identify common mistakes, +improve code quality, and follow best practices by providing warnings and +suggestions as part of the Rust toolchain. Clippy can be run on Rust projects +to catch issues that the standard compiler might miss, making it an essential +tool for writing clean, idiomatic, and efficient Rust code. + `Link to Clippy <https://github.com/rustfoundation/safety-critical-rust-coding-guidelines/issues/78/>`_ From 2a2c269a9b77a706865af40c531a8ac16ac2f053 Mon Sep 17 00:00:00 2001 From: pandaedo <volker.haeussler@qorix.ai> Date: Tue, 24 Jun 2025 10:18:37 +0200 Subject: [PATCH 057/102] process: add link miri Ref: closes #1224 --- .../development/rust/coding_guidelines.rst | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/contribute/development/rust/coding_guidelines.rst b/docs/contribute/development/rust/coding_guidelines.rst index e9a6d5c70f..c170f25324 100644 --- a/docs/contribute/development/rust/coding_guidelines.rst +++ b/docs/contribute/development/rust/coding_guidelines.rst @@ -66,7 +66,7 @@ developed, others remain under evaluation or are not yet accessible. Explanation of ARA Applications in Rust ####################################### -AUTOSAR also shares a public availabe document that explains how to use Rust in +AUTOSAR also shares a public available document that explains how to use Rust in ARA applications as Rust is offering safety and performance advantages. While ecosystem support is still maturing, Rust-based ARA applications can lead to safer, more reliable automotive software, especially in safety-critical and @@ -106,14 +106,23 @@ tool for writing clean, idiomatic, and efficient Rust code. `Link to Clippy <https://github.com/rustfoundation/safety-critical-rust-coding-guidelines/issues/78/>`_ +Link to Miri +############ + +Miri is an Undefined Behavior detection tool for Rust. It can run binaries +and test suites of cargo projects and detect unsafe code that fails to +uphold its safety requirements. + +`Link to Miri <https://github.com/rust-lang/miri>`_ + Conclusions for S-CORE ###################### -During the S-CORE project only formatting and clippy checks are enforced. Also -the code should compile with zero warnings. Additional guidelines by the Rust -Community, the Rust Foundation and the Safety-Critical Rust Consortium are -applied where applicable but not enforced. If possible the usage of `unsafe` is -avoided. To keep the code `panic`-free only APIs with a proper return value +During the S-CORE project formatting and clippy checks are enforced. Miri can +be used to detect undefined behaviors. Also the code should compile with zero warnings. +Additional guidelines by the Rust Community, the Rust Foundation and the Safety-Critical +Rust Consortium are applied where applicable but not enforced. If possible the usage +of `unsafe` is avoided. To keep the code `panic`-free only APIs with a proper return value should be used. The adaption of these guidelines will be documented in the S-CORE project From 130539842b775548ab7bc882c420b13d3eda00e9 Mon Sep 17 00:00:00 2001 From: Markus Hosch <markus.hosch@bmw.de> Date: Wed, 25 Jun 2025 10:38:47 +0200 Subject: [PATCH 058/102] Rework statiic vs. dynamic part nstead of providing some generic pros and cons, explicitly stating the pros of each (which are the cons of the other option) makes more sense. In addition, also mention dyn compatibility, --- .../development/rust/rust_api_design.rst | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/contribute/development/rust/rust_api_design.rst b/docs/contribute/development/rust/rust_api_design.rst index ab5a8cbe1e..425a36c366 100644 --- a/docs/contribute/development/rust/rust_api_design.rst +++ b/docs/contribute/development/rust/rust_api_design.rst @@ -29,11 +29,15 @@ mock struct (often created using crates like ``mockall``) can simulate the behav you to test your code in isolation. The mock struct may also be provided by the provider of the API so that users do not need to reinvent the wheel by providing yet another mock implementation. -Below you will find an example of naive coding that is difficult to test because it directly depends on a concrete +Negative Example Of Badly Testable Code +--------------------------------------- + +Below you will find an example of naive coding that is difficiult to test because it directly depends on a concrete implementation: .. code-block:: rust + /// This struct represents the API we want to provide pub struct RealDataFetcher; impl RealDataFetcher { @@ -42,6 +46,7 @@ implementation: } } + /// This struct represents the code the user writes, using the API of `RealDataFetcher` pub struct DataProcessor { fetcher: RealDataFetcher, } @@ -80,8 +85,9 @@ The solution to these issues is a refactoring that extracts the API from teh imp a system part by means of that trait instead of a direct dependency, as above. Providing the implementation for this trait can be done in two different ways in Rust: Static dispatch by means of generic -parameters or dynamic dispatch by handing over references to trait objects. The following paragraphs will give examples -for both methods. +parameters or dynamic dispatch by handing over references to trait objects. These references can either be Rust +references that introduce lifetimes, or smart pointers like ``Box`` or ``Rc``. The following paragraphs will give +examples for both methods. Positive Example: Mockable Code with Static Dispatch ---------------------------------------------------- @@ -153,7 +159,7 @@ Here’s an example using dynamic dispatch with a ``&mut dyn`` reference: .. code-block:: rust - #[cfg_attr(test, mockall::automock)] + #[cfg_attr(test, mockall::automock)] pub trait DataFetcher { fn fetch_data(&self, key: &str) -> String; } @@ -209,35 +215,29 @@ Here’s an example using dynamic dispatch with a ``&mut dyn`` reference: Pros and Cons of Static vs Dynamic Dispatch ------------------------------------------- -**Static Dispatch:** - -* **Pros:** - - * Compile-time type checking ensures safety and performance. - * No runtime overhead for method calls. - * Easier to optimize by the compiler. - -* **Cons:** - - * Requires generics, which can increase code complexity and binary size. - * May lead to code duplication if many types implement the same trait. - -**Dynamic Dispatch:** +On API user side, one needs to decide whether to use generics or trait objects to enable dependency injection to make +the code testable. Dependecy injection via trait objects is only possible if the methods and traits that the code wants +to use are +`dyn compatible <https://doc.rust-lang.org/reference/items/traits.html#r-items.traits.dyn-compatible.intro>`__. Here +are the pros of each method to help you decide what to choose: -* **Pros:** +**Static Dispatch pros:** - * Allows runtime polymorphism, making the code more flexible. - * Avoids generics, reducing code complexity and binary size. +* No runtime overhead for method calls. +* Easier to optimize by the compiler. +* Ownership can be moved without the need for dynamic allocation. This will lead to less lifetime issues. -* **Cons:** +**Dynamic dispatch pros:** - * Slight runtime overhead due to vtable lookups. - * Less compile-time type safety compared to static dispatch. +* Dynamic dispatch doesn't need generics, which tend to make the code more complex and have a "viral" effect, + propagating the generic bounds to code using the API. +* Shorter compile times. +* Smaller binary size. Conclusion ---------- By designing APIs around traits, you can create mockable Rust code that is easier to test and maintain. Both static and -dynamic dispatch have their use cases, and the choice depends on the specific requirements of your project. Static -dispatch is ideal for performance-critical applications, while dynamic dispatch offers flexibility and simplicity. Avoid +dynamic dispatch have their use cases, and the choice depends on the specific situations where the API gets used. Static +dispatch is ideal for performance-critical parts, while dynamic dispatch offers flexibility and simplicity. Avoid direct dependencies on concrete implementations to prevent testing difficulties and tightly coupled code. From f66dd8e5a70d4654b0719b09690326e1f9935797 Mon Sep 17 00:00:00 2001 From: Markus Hosch <markus.hosch@bmw.de> Date: Thu, 26 Jun 2025 09:43:18 +0200 Subject: [PATCH 059/102] Add copyrigth header --- .../development/rust/rust_api_design.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/contribute/development/rust/rust_api_design.rst b/docs/contribute/development/rust/rust_api_design.rst index 425a36c366..a6baa49b0f 100644 --- a/docs/contribute/development/rust/rust_api_design.rst +++ b/docs/contribute/development/rust/rust_api_design.rst @@ -1,3 +1,17 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + Rust API design guidelines ########################## From c510963a0d4d300fb650800aa853bfc16886f811 Mon Sep 17 00:00:00 2001 From: michaelsaborov <michael.saborov@bmw.de> Date: Fri, 30 May 2025 17:32:07 +0200 Subject: [PATCH 060/102] Feature request config mgmt Request for feature configuration management. --- .../_assets/config_mgmt_application_view.png | Bin 0 -> 12904 bytes .../configuration/config_mgmt/index.rst | 136 +++++++++++++++ .../config_mgmt/requirements/index.rst | 158 ++++++++++++++++++ docs/features/configuration/index.rst | 23 +++ 4 files changed, 317 insertions(+) create mode 100644 docs/features/configuration/config_mgmt/_assets/config_mgmt_application_view.png create mode 100644 docs/features/configuration/config_mgmt/index.rst create mode 100644 docs/features/configuration/config_mgmt/requirements/index.rst create mode 100644 docs/features/configuration/index.rst diff --git a/docs/features/configuration/config_mgmt/_assets/config_mgmt_application_view.png b/docs/features/configuration/config_mgmt/_assets/config_mgmt_application_view.png new file mode 100644 index 0000000000000000000000000000000000000000..d668c4cff7c73ee6f1f75cd68dfb73f10419fc07 GIT binary patch literal 12904 zcmc(GXIN8Pw=QlKb<?(@vJntP6af_l0ci^mk)jYF6e)rQh#*a>lm#LJ3Mwifgcf=T zRit;z7NjLAp|>q9kWiEmLK4cILH)`-=XuUK_x!j&cpxil%{kYYV~jb*`@TFfGSuPu z{lM=W92`7)x))41IJSmxaBMlU^EdVtP8k^d+TvxRbDpCZFFXT2Y(r@pXmW6r#&E4( z-wr<S^3b*P;^5$Y&;Hrc;+|&@F7ENxzT%B^cl7qV?&-jx<LThw=5@>6+tzF+c;w8e z-UUt5yS8(~tXLbL)NkJze9HnMhuf@*PYj$EvwCHCNZ>N}nPU^O;?KOl?7EWJ&2eOx z&~dFl%=L5)tmu#Y-$W(;;imo2=-Jzdcl-LTU5hnQs7^Y>eKy|nWxNB;^3%1$wW_1- zq@h{_W+tu6i)k}bB5Jax2A@(x&wGt{F?;9`SmLw2WPb3gH3QlLJ_!GhKYYZ#efw5h zV_^uU4}02iXM$lqN|<4EVh*nPr3<*#&Kv_n-n&ssliYg9k|@E!5v~PiM&=<nIDU_0 zUZ`>zD0d<gab*J@^ED*5;aank=i%QtjLs1yY8@uq;$<3^zSOy%3tIUWZ()nu&tBwl zu*P8%oGF=B%Ppq1u}am_(jxyx+r^>r)d-XLs<gCpAB4pOGqnY-iiho!p06I~MVIVi ze}BgqlX%(;(}hK-3p-MJirA~!sR`eB=K{AKddS?y!SOW@arsYhD~IyM&CBzig?3HB z?JrL*%d)S&`!T>^5VSUfu=5-Ck?pH|!hY^>9^rUaw~3vd|AmXGc@`{*%4-qdA6??$ zxE4f2Jz#p^OeGVf<OQn=%;&p2?JzfQ-qZ=2>P)78d(YSY<{2Z&2*bg#SAf=U)i7X} z|8yXv^TBgZyO0X2Gfw?>-6%#9b~>j`o<ChXk1*4PmGKK2<HuA_XGYt<3Q{7}Z{@i6 z2N88C%Pg=5iP<8ea2;obOfpd~EtXI~?B1S_5Zv~?_y`BbA5WPs+S=HOtTv-jw4qQU zc>wCp?L=;)=>db^J55A!Ee;q&`Y)z3H#bqEC6D0ISZG?`Q!aSm?v&a&?Y%h=3pP}v z5xWrTS2@?#ewr^L-)vRVNj(5(BUfZeR+P|kO$PIZ=MiExrOgY^`OYSCbN_P#L_QT+ z@&>J%P~(0Zr-I#lvyw;PHNrgKf6{8{gG})EB!xJhik&}qbNVI5cPw1M)+l<@K)kd^ z2ig9`_5igDKiwpNy>aOtd5EPyem!-V?Q!oipwC+W!Qc3d*_Qr)9EjSA2wtqE6c2_z zQuds9xN4E<wK;*DLtESvA;opk%O4jf+i`?*o8GO{O=^T$_V;*=F=u|xD!79t$p3Sd zcZ~j%%i>osH0KaI|A{r=GbJX08*5fIC8i?r6xk@|<42n>`l1A}gSLzPhCxc+)1Sh} z8J{AdCBG25pX@D7a{-HwH3ZKbA{NapB1xwuw6DQaR%&I_B|USm<6ozFB_tUbd^hjY zBBCy{mtK=eE;GSBZuVO4N41lWX>8BY*Gr8z)Z`?0MdYG09gWIrP+B^-<&{o4Bc3Py zDKD2S=>R*GTgeJI$2WfQ7+$~asLT8For?RIac>{g(|WA=OAt6MiT&@%NW9H}k`Fwf zbP}18M8pauNS&qKS8$d0DN1d5)SLa&0u%ZON>^p>TCaLe1Cy9AS20q9SRm%k7&;kU zGMFjpNiEBGlmXq`%q;Os7*@H23{0qJk-HkJkqDQ3L`A-St3VRj3J*K(VH>yjY!9|g z^J-x2gpJ#mnQi4R%Yvn3<QWOc)HrS&f_hQxgK1V1<eDrMpKqC;0S(9Bs-KsuWAB+~ zjt|Tv97t-Puer$Y>(>0Ch|nr_c+l&owRSPWzmvrWn?gcrY+f2j6;aB}cd4STiW+#q zNnM$Z{N=zYo7sN(>={}Pg-=#=r-`#xN$O3vK8y8de_^8O5lrtK+7Qa>=bMX9h^~JX zU8mV?m~qDDK0%FWzk(<g&*RjoY5RZ8sb>u<)X#S{T!t@Z{V;;AE}7hQ5jz>E=imkR zNXaHFtj)|l!?F;`AxSJ-8i&tdhrWnN(a^W;<+swlxc(Yw#sKy`bp?}qXxNuKNaM?0 zZ<~wwLe#gkwcaN}2XG=85Hbch*rCJdLPGBS!k8X%uD~!gcUkT7)cbSo_#M9aM^pF~ zW=jrwLs%p}V>zLHxh(cRZRSCi)hpBDym-nSXH_Qh3gq2-s;=G1K#jN*`A8pDR@6|q z{<2$C{=m9z!Sc^Y5EqZ8&4j4ky63mYR3|Mctv+>3AqQD}>~bfG5GeP6i1nIBmKZ@n zXT7DDSMzGyijkwLS6||V7;^<XgHp-KIxn9@{s@OdhxK|$RbsBAjSW^sZHFHF%_F}Q zJ+}xwwqnX)D4SvGU5XK-{1n3jN!+wu4|3B=oTLMGm+g}$Qu~rgC0A<R1{{URRwYKj zxi<YvSN8^u5z<1n2%%Znt&Ryee7awVm()$@O&Z1_7KX4#UPH9k&b#GfYRrsj{jVI! zawpk-v**QSxbkLOoFr>`F81v?@A8^md4u@Q#=miGcPL%f7ZC0RP;ymfUPU}JRVuz` zsm(;OSnflzPRRr2WiECoKd>)@_8~prRi@`Ae|e>+7z_`bHMMG>=&q2<oTM+FM$BC_ z_$>8#K{*rZy7yz3iU@98G5C)3Ukm?CL8@;(RqM(7+9HpT_+wR-%vG*q4}O^nmrvk> zr?o^sTrkFf?8Ct!F0MvXI(P2w(zLN4M=LwNbV24l&Q1)wz)2gvIT2AJee>Q2%x&yS z;obuy%suuI{p^`(H)-dmBb#^YA>iPB(~|7(#j~+cs5g7CX>jsCya;anWI&YogMCh> zC+8s!9bm_(qA^C}Ec<r1OepjgdyHWaIG@?et_686lbtZVL8`ov_5X38xHP8f?@LKT z0%4o$lH9ab^|tBMx`jsT`Do3}Wyj?+U3?aICAugMvlq;vu_q6q!LCz)Eg!A=lX2MK zzDfbxyPBJY&9gtq{0xvAQYgiB^F0bSFs*yi)AFBRA^)?w=6oJv;!R&)-z6w||H**G zRtbk|AA=0oYkF}J7TaM88)6{1czno<kb3531osraVf?9zed96q`t-7(=UXcwhd;`F zDCTT~@67-g*x#Tv!L#f^WW$&jc>9>%sh(|;q_n_d?py?xz5d-~ex-DB*TPt|OfV?U z?0-xuek*&Z*P^)f(5-SSXCE_^^JJrm57CB5*_-pV5(>RMJ&3dM2(8OcxB6hSFzqr4 zN}5rNgU>@ht8UjwGsg5^dwN7<K83b!V_JLXN;@yKz>nK&jM;7B(~LtjoUan0HKwm! zG`%CJR#uGg!(`G8zCIrS$KCP$WI2BF`y7)T8?v}qw-|oQd6Af79sy#Pnwy)87a4sm zP-OtkS<uF(J6n|+{8?Lo=a7J{|KvVKj-i6Yna;4XLQXs;f_a#1vy4A6u%k%D%js^6 zRJ-Sgv`^mm5qP9??npKy#N}CTD^#I{vffh{5WJyGn|i$Xu&_-n(yBO)#Vl|>8Orp2 z_t{T{b|SPWPsnM%X~*lpp`JL=$|f7%+-i{PG7`FbnUyQ+&yVO#Bt$;0n|<9rkq~u1 z11i&)8|gNFvwr(nVyeH{@}OhMi0TLIcilLZd<cuc*m?~Gv*rSqXG;?#C|7mzp%6y9 zU1R9uWI2?fJGsjd9XR$WB;NkzUl_$QJ!O`zFRMi12Fh2U{L+lld&8pv5}LHt0L1P} z!+yIyGymvm!6Zr-V|P%MoVWB;%hIyL)RdBX1%2Xa|MQunsd@6$J_ogYC_%>VRMUC; zp0{B;aD;c6ketRGy0h4Ju66Fz@a(g>w;%cmiiq#kf$KxBX_8^-twjjILuCQxm@ilG zVO=%)k*P5O;yX~4e4b^TRT~{)c2shgUe(1$IFuKv`0&h!lT2+f6qR<?a)X(D!v-Ju zaz2_bi3LbI=aHT#lM1e&GcCrj#Xjq(RZxF(pta%sf;4onbL5GZ-Tgj+I$N}P1v`-! z3f>zP8(}_;%s;p)9!?Wn9W1>*6=6c;a}O+%(>Cv`K3F1OXNnm)b@9QfQ4|sr(64XM zd9z2@62o)b7Yv<8*vlLj-8jxyw44XZXR#~@i4YYDO3{j+C8ZAgQ1^EF?fockjp2*P zfTG7b6-RBVJ-*g2FVX3PqkaQqq}|cd98ty|`;m^rG^gA|?r!9&w72Lg(@K%$60cm~ zYKwXWwZK!uU+Ypkt&Nuk^cTkttA&l^QIW~IKG?g|>G*2uiV;S#{ASBjP(8*jatIM# zJG7e?nP9Xp!nvsf^tKV}*sT{<PAQ+$UYHZ|8}QE|du0*OsI(g2IV(YzAzgU?{d~fQ zXo2=?s&&3|`WA4~s^>W2cdqJY6QV#zefRY`tcQ8tbmy)*DXo&fcAhOBE0(*0!Mh^M z!kfSe;)eb5YG0>f7!u=aroUA8G>>qidTn`dp>6>Zd`$Afu!L!r9z;}|(vIIEVX^jd z$JXHV7sD7ugFAfJ&95ExPxwpXlrhFBHk8>>{b_o37g;Xc#1wNqq;w}e=g=L-dWYA# zDpFbHQ`>0d_O)wQ$#SttqBgtvs>Y1zIa-mtskgL>%<EPc+q=bxsAF@ZO(B&xn;#2? zP!&UtY#m?uJ}zs=PcCz1dQ9rJpNe2!e&kP`Y7KK;o{fQLZ=%xtbGaP}wxu`1JND+H zX#EvOa=;#kyQ$O?R4a4751GWi84awx^ZrN$KM}Q)T(*^n%66`(_4xYEQwZ8%5DIvW zLGOUhCR3S|k`VchRR$GDsLzCu=etQI!8B?Aj|^cb=o}Bt$@cP#GQJ-9jeNn0i0xIG zZrN0_K$#112c>fTJFJek2PaxMvqRh(BfB#b@_Nj?ybJvKP0tt}IN^m5=6pwtNc|C< zLf73ka;Cz3XfF7_J{2X30vD2_B$HN&3Lf2YA4Sy<Z=R^=3-Eq^8hVdl9zscA+8*r{ z&#NNZ?eP|!BMHYlCde=Cl@WYT?kds{3UZD<OyMS?>O>1E`%ry9L#X$VBEh1xQ4)Il zj}h%D)crTRat#t}18@z6dut%Oz_|)`C;T;1^yQs-;Di}u<U#kUq0EEu`i^T%N|)2Q z-If^Tf!PZDUd!v_0rfqzCa}JIEjtst2#FR7F~%h}kA1mVQ+VEYwy$&?iDAZZKhEqX ziLQT(44kh)(a7DGUY;;E2Ca^7jhJ5^A?}$@QmJ!ye#PzHwl~kv@0RKznwdgx$|-KV zunER7s@2F2PTHruYdR+*@a<Jss&W{ue|`rgpe)=~`}1ufIxyVo$&gicnepN^^DJv; zd;jON#wvRo%AT!7*Xi6wdbCLJw`5gK-U`7z*t^P~kal-$R|Q|g<V$O@Bo)N~BxX)k zN^9n3(-$ym-^JFHy}@H9TCp=5L99#OV<2qKF-}&q%;2{jgA~3VTJL6b(8JEroGfxK zfOvVS&#r--@(~R(UNI&-tOKGr#Mk-H16=_XMGQX#^R;_OuXGGE@5tzzH}|+7kEO7N z8Um~GOUGt40*x@PkktEg&p(?Sl1(W?q7TKK9hbIaM3Hw1{wa%0Y%L-@=8DD(16Mk# zP3yl~=&AnhJzby@I;RJ>*;VC2YnYQ`2A^+prB$Ap%aci>yR@C@Mjy9!x4m8fXQsKG zJ#nShCBwR4{`FgQ=My@lmVJ{&Ul8>Snz>}hoJFZihh-dQ)e;2kf{fRklTX^#-<|oA zLw+ZSO8MSh65MV0_}fU}LhG?E)WS%^?cQQF|HbUb$*MFWvTE3O@Y}a<X=;J8rLplF zOFcvaYX%Ww#d$J_UN;)w?W5JM<M2_kI8n6lrl_W4-?wKL^*dfyDZvVcWqc?vJvZlX zl{0D)5G{wX?(yX2NWK5!U7-UeF^x4|q_%6f@)Al|9pVjg-b?FztZiUpGoPAE;t=qg zoodw2E6+tcX_7n=w@)MOWz0o!t#6yF;*>6+vl6WIMM*>BmL7NDH`Jb?S6)j`<M8=G zgFfcPiX@wTiT$%4aLcga6IPm^8OCnqodB^!;VFP7)GBDWr=!3r{V7FN_QK^3?Jq+^ zw^SrF(MJMxE?#V;H!NHYW=w)W3H&>Bhy7DfX9rZQ_9Ei+=Zbr<s>hS6V~%)@_Qae} z!={dHM7PtgQ1^e9d(e%g9&)8gs`DUMLwaXgQoSxExg`fb9{gavc24BdOyJ1#?I5s0 z@k=|CH5sZYs?P0G|J^71uS}&IlFPS9n9LfK!EZXpl+u)T$Q3!=Sx7|96xgdRCz71{ zifhd`PB?dcl@s;md&b}82)AWF()WVRrQ%T-*qjpraFLv2#|qxB@yJcl_<Vp|)sgcH z>{B36CM?EcK3+Rtdlgf3FupM|A~*=QLVbsaFZb_=>lngYC#TMM_M6Dvm4J%Abt*+G z4l6WBu~64140HL362~4hx5X_Hv4Mr2AB_z}PtTsw<CXJ#>{I|5ETgx^xJxcP?7I#h zkS+b*GmuPjv2e$;R$`{m!^vkfE1?k4+?_PW$0IQhn(3JJC9G3duG-pCmn?4?%v#RK zI4qcbnMp32DW+67zWTNlS52Ea(YN$0!C)oa<rIS%7n#CGdjtTvdoMDX#2tL}S6^x9 zz&EE`#C;N<-+X+zx8<OvKCf;-6f$(a6e&td$*Dh*Y1O78D=*_lx>G4lyr9<9?^dvV z?gD*WJqhLO-n<RRRBgZ0EQkvF7A6`O`kckAUu=`^zHZA2QF=?<ecYF=>wI06)%nkY zD&l)yx!*OCn@r4a=o<%RLYcyJwBOYzU!DL%`hB!!NzhOygU%g_ZfL2lo2oX2+rs7w z%ZOPEB^%5V2ag^AV}b_d-iutO>C&C^edCdte1{$H2TepS{F%ioKE*L!pYuleLCSdS z*TPq-C$Na6EeKJrx!uNuvBIXW-*T&|(^{$T)%FaUq4l0{IrF^#yJKXFY~v?{jdLNw z=a%1wmkqv?dW`Az>II&;+UXwb^)+0e?G4Js#iggvQug6evygj7;u$SYr!PjBil~}0 z#=*UY+B4F_xb+lrFf4UFMt_uN=PFO`bX{ys8IDzt9`zSSHxjv4Mtvs6*AL-EzO2QG zy7xcqRHEUwxhFTS`QnPZv360=on4k1@NfEUWd2l2IkeVt7w%Vaq)4tGGep4$mA!AR zF=?{jjJthWMEpKpQw6Z7kciLvW8Ej_w3#)NiPue;rcO0_%1X3;S7l{anW^7skDhLJ zi;ije2p?VRedXX>rV`Zcri`q5vEom&PGPWFIc1P&z;uRlh16DzbaD0A-9gcFB|YE% z4&!S(BtKAuAXUxe^`?$qi=rR}%HFq63ip-XY$<o@ng~@qNK-t_u3gw2s{c2uSkaA@ z7B3P$zF?mntj}?LaTb*htr;p!#xbZQ8C~?zOE1|)wkJPKT-sP)*m(K&?mR&A2tiYF zubYYIs2y^H0aFd7kQ(|N9W9rCY|^;*Ab=t*?PqWVNn~yca4yod%%{RiVjJ<(!Zb8u zPL=Amol<5i^c@ec&yB9nCA&8=HcY1QDhsRF5T-=UBj|Qdq0`1-GW+Zdq`O((bdGDE zyn~0WcxXx{UOPZRWQ5Uvna>=mavya+bGSW01`Ca+LsZ-vlZfpJDq(rcNY4aKt<7LD zyld4t&J_V0YjjWtlKVEOm<=0F+?jQ`h0L!$m=P7HJi_I4DEb7*QCqzqvU~mxEbk^x zbO~`ZmF7S8*Q0PQ;6@~1zp$_{;6^0%4Msf`AFG*EeiakNs+@n5T#aK7vKCBD9xZ2n zd2N#kQA2+W)yzzJ=G}w!WK1SRj_k51wqaz6uIX|XxsKG=togM_;4&bId(4h)<Sv8= z(y=qC!oKx|kX!ZF&pM)O?E2ecVlNHN$Ht;i&}1F7&_EwKX<hm84XL+jo%ZI9M#D%@ z?x(Ef%1a5S;x*fhFxxd@1=jFFFrBcmO0Z)M^zJ`plei%M&jkhbk_O$Iig=AP?8=LL zDN-7ufwN}>cfb_uQL9(i-hvigdOR)z;=0d#{H;y8Bo9K4+#TmZ$H{~jBK&c+!SM;f zJXbo`DidZmu^(z{56SC$b|n<AbI^YRoTo3i@7so~`S{$zsE4f257)&URAZ70O4wmA zSm~OtuSH1AjVwYiMlpYo<&I9!Kfjx+8ZDm3$UYP=XwUT<@z=?*Z?N5Hw_6vB9mqXc z4?ICoNGSHsQ*k85b4S!tC|}UuLZd4Y+*Z%JKXiYSze$wHBczznYGeVoaX?r&PV+Xd z2;l$_CB>1uS=>o^)21ye(k1mK@zc#ugt{>+<SWN}bK>(6j1c$hZ|`qMrTV<&wn~S( z{sxt9!l+K-rBgK*=5!rC4FC)KSYGW3+F*@hl)R=M3(85w>(|(%Df{H-&qW>#&@FZ& zsL_YY0Q<5l?snTzB!-M|s}ZVD@S7jXxs=d$sG}c+Iav@bJu!r;84JoN_IJ+-x>?!S zL+{+neDcb%U*D2Y)4ulLWkkx{7P8zia#{LR2fAw=do#D^<w<J=m%dNyksYYifqvZ8 zH120N@*(=ds7%-{<GJ_`Ox57k>L|RmTTRYa*I5a}l<KLZ+oqINu<J3Gox`jU(-xQP zt!~h8U+g&fGlRnbkjuuX85f$Sm~kb8-AE!gQ$;?dEF-HTDP?~JR@dNh61sCQNl39H z+$yK!tWDKMlHdz1HY~f}6e1)0>--i_>MTni3H+M1!#=W{bd)7Vrg3HL&6_ub;AJ^M zMJ12F-z?2^A<|SO$G@+B<qJtv3tTQJX_OkbIer1w7f~+#(;VYD^#zZkbm5)QW5jG| zxY{%WCs6KGfV(}XYFK|PoE<VJ@`i}m#l?1+(Ev)3fQ`pnCXM1ZH_$!9A0&7lcGNyY z@d8#-2SgG88JX@g(;^n5tP#5J{E%dr&2bHQpr?F;i7mIlFkd(HsL*Fp2hI*l@;Kup z*Sc%H6waR63?<D;9CWgxMD^~szegGZwVER3MDqxR$FIR7{-o56m6(m=VY>NI0~;=p zfEFVLUl{nyW4@~gtL8rwI5lj6S^kh3a03bFo0;i1elqR#oR^EuBiwJZgZFQtq4zzZ zN!nd;;H~8)O*~Qjtdbi0mYE`dyT?6*Wi5Ci05Aqki}58N(|N!-(B6g5SES)Qje65g zDJ3L(D{ncO3^&_1&3Dy5*FDocU4o$RHpV6893XdHebh{W%A$dN%8A%@eoOC4)~7(} z$@^Thcxh8>X^TK*2GvTG<zUx;3Z*`M0%`>>bjuPm($H?ZJnBWf`dN(wRS1m+E;LY; z8OsAt9nCk;8;dd<VqvqCpXhyKYT7_XO<h|xP04c4K>yR|ANyfS#GcXx027q6#v!s1 zGwf^OMnQ6>_F!uT=k31kN{7lahnaE5Ji00PtH#}=dVgw!+zn7BQb~k_<dFzaMAi@^ ztlb-EuiH<>o^%*(QD6Vgj*n|!3azW=0ZR6ALlY1PJyN0Se^atN`3xM`v_R@?rUW0G zBC#|ADZ2T-a8a*)3rUqKhQ057h^a1&htu*@$I7$3l91}jH<t}gS`-(UCaR~;9Y|@y z`oKvssmNIfpPIQm%p-wJHDlP>EsQAC`FMGjpP+u2Hw7L%0B@dJ`B3}hV(8<(G8Ezd zcCLxss*Eh=5P%v0&**TeUlDj)L2<1<XRISgUkNszk5>7lY~i+HL@6up-)M>L@%NcT zov~LEMoa6TFDa(p3ou0KNb->W%ISSN!i^WZE*;XOAhsj0E1dkgiW7&h{A7tu6AL6U zbq(CLKI=(6xotjXH+0fb?ZaPr=*)KcAem8!y~=ZRr?W(oZl{Pn1?`uUm7b#Dnq=er zK7vPxS43GnZ1z&8+=3Y3zXl!-Y2gUBe)xAzI+S|jw!POU8{&uD<#=0t<<>t738Jib zhPAJ{+jwFVt?t5YBbJqu$(b|B_Mk`)r0xymqV3(qJ4%o@CZf#Ctudi0`F`pavKAO{ z?8!8(z6Pu@b2^KCrr3Yt^!db~m4uuG(_6#JtjnEMO}~Tgw~pUH`cdY>M4J;8;pG>z zW!})tyWI0V{m8>9$>EDXvWXPN-_Keu7_PLc>E}xlOfl>4RNDRbZ3FaM#SgPVoerbs z9s2fn=u`b@0IoULLHl5O<<OETScf`DE4@Y55@EWaT7kcR5O6r1Hr^6bVp(>Pv*uYX zvz(>e?zh3+gYEZHR#Dury%Y3$!PS89_nc5_s<SHoRKVgUf3!V*%ul37paU{q&}=Rs zJVT9SnY)?i$RwJ{_hJ>pZ2zjl_$ZKFKlB?j1*+uQU2~ymTq&fIP{TAeFSb#dM>K#+ zy)#*{J)P(M`}cs&PT=;;P^9(OXut~l?BR09(Zi&d1;dI-SIalz=K~OVGz&iF@`z(p zuv){2D<=iHpzToQZZ}_2B{UROC*=3ir)lFVpFEw1V}$3KL88N4RddUr5Ry%EZjX;* znqHo>^d&h|v!XRxB~Oy&ys`X^o+ugfeBMA-b%Ynjp<gM9c2{$z2-M818+Da;Mtmmb zwvEp(urrz?+(^Z%0N}hHba4(t7jh=@%?j*4MfBPRy3P;PxCTGIWo};z!K~6l?)2k< zPGwuqB8PH`0x1nS1A%qXiK&$%uC-nV@R+55@Ykcf!%<3qOc%^5(>l9Y*Xtg7-G9@I zYxKA8zssgh2>10b!M@35q&A5k=R+GvHdO$O^O12~d4S)#gV*Nn*Kqc!{CLod)@`Bw z?afx%kI|RYSaIIBC(P3O>G_LPpL{Ca_Z0-!-ICxjh+u9zk0kV#?`wG2A9aB2Kif&Q zC>*-hut(IV$RZEeXVXL_%(Ef*-|K!%YYOKd@skGl*OZPr(^#<l<p*XtuPCH?_N@0h zgT(hI$V+u!BZO=NW{%d>s)3MZH7hnA4inZZgeKjH12}A&l~la_e}ldP`JPfk2+D%W z#)@=f)Rz0&;-ww_&@;C<y}@eQ2&8r@x(}4=H8TLk)h2TMizGJ1la%V$mcHFGb&YFO zPh;5EZCNi~|HM;k%!pV(fHkeZexG(x5pls3SDtI}vi44@<cMm(Q6ii4+^!8f?gnMx z4!(o+02#Nxmo5R&8<06iN^eF!_L4v|U0UKKk;`*~5@FxbFZe6B%MZsz7}S2JbmeAz zAz#&bXMr)WK6BsSS<yMl{84Z(7>tvM(wwY-z<JF8g-`n-06_(T5_Tk*<w{F5)ASv5 ztpbJSY|`ywJ-rlz7acvQs&E~Y<Ie~xV;3MR_*9kNLQ6TAxuhMvzm+(Y!7h83tn2UI zsj(TUzB3Mhk*6Xm$B@*5X&Mf*Mc}H^j(+K%2XHQA7qUik2PJd<IlqMwHRYuKrmR6N zcxo%?98y>vJAPC|i^dpGWTlYt3n3dUS-c9FeNu~EGK2HghZo)fv<tWZV+oi7;-5+J z!q;r9vq0$v98co*Wek8(4U!e+Kp7T)ClR>(9H`+p7?=&oaqn1w*7(j1$OkUF2$ml! z(6TZH4MiIBM7+M;`eK56^AE0%0RT`gfRQBi0G&m-bGMXWxd(Fwi>-tZDd*0Ftgo7@ ze19LwS1_o4`gHobYQtERG?7omhfHLb@J|#+o++6)0i<s^q%l5T+TxVu>kGf2p~FS& z*FeC$yu1h10!%qIUIY8H=>j%_ksntN2qpVJK)ZIV!oqdEU@3IRK_j)zCgvP$3a?K{ zs6T)EfSZpGiJ8%1<Nttt-0Tm!8|%8Ov`eh3+yL4kyR*!t|8+wkz3q?#h)&Su0N`RT zSq`&!6=S!-?Bx?acW5i-DroPAs*O2|QbX1mGppAG$YqB%0e?1bixuuAwZ=-II+JMg zbqj5MsB70WPHCHjTi{IXpB)1(1o|*QRsIgTx+gRxtCQ%Gb6!m)mt$qbs0QA-S7r(c zBuq%~+(3owH^y7O;BTNSM{<s%K{*Xt6cxeji(25^pNiH962;H5?yJx#<MlFG$R91) z&&7(7yEZy&n6FtpHI7jm?Gj%sF-MLZ$tanfo#tW^*Vezch$d({m**oE62uZ{7W-71 zbmB8c{7xY;XbpJ3Wj>j@CmlGquyYf1^o}sixCBA~Ee`PQp(I%V`Odgj4Ifkdi~^9~ zTuAyC;Iih0R}SC4`~(0q6=oQ`dzW#EN|PpF(SB^$`rc{z8W~Pwj9?GwA$e#s^ye`_ z6K_Jds$WI}a?*{2PX(Q_Y5aOi$Z8~a^UYC=I2a6o^A)s?z?*Qu&vsLdwksRp*w^P$ zSmpO=mL*T_lAta|2Wvb=Js9MU_BSZ%RHr)gbBz7zG#(*^>~AWe%^_36&Uu9ANh;}( zTqyH|>?Td@c!fp7A&MBI!4rYw#>x~b@bL`MWyVA-f|rM<^_r?{qY89=t_L+vff^JK z8gE(!I1FHj<qE@?<)57#zN#&>Wok#SQ<~N<aY7(N-X^uuSzy1}9nof&`}=}F;WWAI z<0cJ_z7DqfFs_IID%wFny*&>l@FP@9?OXQ<mK&AyVhvN7tkDhIW;V>iuK_#$1_FAM z$nJOrn$Jrz4QD}v^ocKJ6rh|@`=rm8m;^7EVR*Q?vweFJ@cwQ8dOLP8bs-1^(zNW( zfu@iq{SFZo-xc+HGXhO3A1ZonRlxLTM+0%coEyMPg1O`}^)J8j`1vFXb=Yro4Wwii zYoW=mSu=#$g)x25iBY$6$dmOUo9^??u;al<kuSD|z+7x3gk5E{r*9|At!+jDVA)X- z4RQwq_Zx8*<$ykyU&64^s=^sy!LoRWfpDJ#l#^wp3!2+1wtF+Gv)If$Dy<VOM*`xz z=bDZU>r4vBK1Bn`O@PmlmFxvr$m<}6CtwBtF-6*B7F4w3;N5E;9v%QL;)7QH{yyF^ z8bmeNWCuWMW(O~LKmV6lW_eoBV(Z*s)h5}w^yQL+31BH0z}tW9EA>PO&2k$^2tR`J zvsDkt&0ds-)~<vmEgqi8g1Dl=P~p9#lOMUra$W$Zli}-^XfoXk#2y#8N&vNe`po}Q zd62tABypx==NnmWo52E93CIAlmxsr<>*+eb#Es(F`4E5yq<#t<|5ZD&h-!H%0x*q+ zdLAx;QvhvI0W{bTeZ_P2XaSjEpbxNhd;gwKy&kaFKZI{=x*w5ag6pLKkY<%i;N#)J zas7H|D*%HPnJGR!mKJt!1-D!M_opiJKNW=HPXLjh$4r4>X2bPLw_$y@Oan~k`KAZU zeV<MBe+dV7u;m=~oU}*6uV{>HEuRS>+(gMB!NqJYaM6h7A5L(>ruxq0B((h<CCz@! z<N>oI;<GcZq(oILOQBl|Hg~EniV<z&0f-^Ty(PdLXFxVmW^Fn82F-JS0^ON~&;1$C zlV&<|#2}{Yr=tlri|!lC?y{%<DM~0yx1F<K+}e=mzieqfhcie{>_pnsLhY&Ex0fG3 zd6GI#WdkJqn3V_Ic%?|x$fh1aZmTJjRF=l%&VzZcR^+PgE_p#zEd@mSD?}q{9ql(l z<>k--NBaym6KVS$Crk9p?b@GHTZyP}qV7ec>v*vxbcf{f2*iS!vZRC5i9i(134f0h zI{`dq^GPRCyZ(pU2L4B$Z=mV9k|rs&b}DdFP-P#}W;XH6&1N7*JRbHT8u!B}musw! zu4LE1T+f|4O`4Phod?VPqo|pPoSh}C)f#pic90E9{mG^{f%GC9B&}>~xfO-wDaq~4 zB=+vu0tnC;^Bf=nWgxY>S6v7F(7y>ns6-?}jri{Z5+nAW>;WR2-`T4M?($1-^553( z02Rvrcn}~K@&~ZO+)zzf#J}kucLDW}AzIdfu{ddQ{X8*5ga&ku?1h<_Vc3GGEy}-S zaR4a;RnHG`(s_1;^g|7KezRozA;8-C6D4HFh@?H-Q?Le4KBrUO=QQfit<i6@#U`f3 z?Z??g6|m?70H#IqidZS8fipRbYyXL7nq04ItFs{yfTjT>y?AkjO{27oE3szF9DMGC zr?5^~=)*~^pV<1^nxRotakpIby7TZUYe|ZdAFiLc*FF57Dn4<55AZMcSi677N9>D} zI_hJtyd4m>LP?HMNt&HgX*?oD-4o?`YTC{>h#fAuakQMz&aF0iW=#F}KCBY-VI_8r zxcMgk6Xb|3!rPvQ7))BW+lX5R5`@a$020)IOwLuw(L5=i(`4m`k2n^=1~u5XHsBEZ zP|7Ut)|#R0F5_FR1yU8Q5Zwu3%S`j9cVim_{{zIs_MR^k=8|7>&1_GalV%n57|RDU z_2fbn?xIN2Jdd1fzG=RrWJ6)ezltOGc+OSyLcoq8Y4!wF>g8mbWx+Q5fgT+ozlha7 zUrGA4v$6ncK)_@qc~mdw-S^DsQ!jv4665clhp>>MbfxU4HK?XX{=C^U=bx%a3=4?i ze(bA_Qxha)OP{gLg|dE%1}F4)(44Zm7S(XWHh}f$m<)_GQkj@p@0!9)HCi9n7*;4V z(b17s4BB!s3F|HNOO$%H2SvJ1bNc;@Ys(vJVoTPztf!+|7=5<MZRnHk9PqXP_6F5_ znPj?1ePrG$atrvZ=I%WD-X7w`%?8=OuzJT>$zCUGl44&>2<J0y_^r*;uEEM*^Y)jI zZr|*D4X^tT)?MvcTlWK+#}*~MpPI*t(E|$&13qH^c+t9l)jVbbZt<t)QQ}^}KQ)gZ zfMDmp(mYzYz|fwU|E<*V<32MCrG+hBW=l)h?HuyiDWIi6Vu1Ws#~vm-bc;D3^eO-f z;p?57-5U^2Kg}lq%%Js}u=2prHli!Z(e9h+B%t<AW@4+%FhBr99ME4gjMu*%;D8hA zMUQo6S)7M+x3jasS8o$cl%&#iYojg$r@m|<pujyKRW#xw9z^Re-*+St>zkE(D}LHf z1ZYhF2?hQIK;&OrH8434LjB(o$KSCnBuMV*k5EYWFolDs<S-23V?Zq(#?~8pOyN^m z(^)Z%QGZS}?MY>e36H0M|5wP;iD~1|-M_gmBh2)FDHwlRL>SkQ*%YAz6EHLu*ne_N ltAQN!pa1Jb9DQ_S<7SJ{_wF{EE8rduJ#E7a#pkcx|36IXG(rFX literal 0 HcmV?d00001 diff --git a/docs/features/configuration/config_mgmt/index.rst b/docs/features/configuration/config_mgmt/index.rst new file mode 100644 index 0000000000..23aacbc10c --- /dev/null +++ b/docs/features/configuration/config_mgmt/index.rst @@ -0,0 +1,136 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _config_mgmt_feature: + +Configuration Management +======================== + +.. document:: Configuration Management + :id: doc__config_mgmt + :status: draft + :safety: ASIL_B + :tags: contribution_request, feature_request + + +.. toctree:: + :hidden: + + requirements/index.rst + +Feature flag +------------ + +To activate this feature, use the following feature flag: + +``experimental_config_mgmt`` + +Abstract +-------- + +Configuration Management feature is responsible for central storage, verification and modification of individual vehicle configuration properties. A generic interface for applications to access such properties is part of the feature. + +Motivation +---------- + +Embedded software usually needs specific adaptations to a particular vehicle in terms of configuration properties. Such configuration properties are called ``parameters`` in the following abstract. Examples of parameters are vehicle geometry or geographical region of use. Parameters are used in manifold computations and are expected to be constant during a driving cycle in customers' hand. +Currently we differentiate between two kinds of parameters depending on type of configuration and related development process: coding parameters and calibration parameters. + +``ConfigDaemon`` application implements an on-target data base for all parameters used in a particular ECU and a generic interface for parameter accesses by user applications. + +The basic idea of ``ConfigDaemon`` is justified by the use case of having only flexible runtime dependencies on parameters from the viewpoint of a user application. Generic interface to access a parameter is defined by key-value principle, where key is a unique name for a required parameter and value is any data related to this name. Runtime dependencies have an added value in comparison to statically defined interfaces for every specific parameter, which must be resolved at build time. This approach allows to shorten build times and avoids the necessity of system model changes and following re-builds if a parameter changes. + +``ConfigDaemon`` is internally structured as + +- an application, which implements a parameter data base and interface for parameter access and +- additional plugins, which handle specific kinds of parameters according to OEM functional requirements, like +- coding plugin or +- calibration plugin + +Flexibility of the generic interface is achieved by representation of any parameter value as a string. To convert the string representation to the original data type of a parameter an additional library ``ConfigProvider`` is offered. ``ConfigProvider`` is supposed to be integrated in a user application. ``ConfigProvider``, thus, is responsible for + +- establishing of communication to ``ConfigDaemon``, +- receiving eventual parameter updates, +- providing of typed access methods to parameters towards a user application. + +.. image:: _assets/config_mgmt_application_view.png + :width: 900 + :alt: Application level view on configuration management. + :align: center + +Rationale +--------- + +No objections or concerns raised yet. + +Specification +------------- + +``InternalConfigProviderService`` passes parameter data as json string to satisfy :need:`feat_req__config_mgmt__provider_interface`. + +``ConfigProvider`` library translates such a json string in a typed parameter accessible by its name from user application according to :need:`feat_req__config_mgmt__parameter_set_access`. + +``InternalConfigProviderService`` makes the usage of methods, events and fields. For instance + +- ``method GetParameterSet { in { String parameter_set_name } out { String parameter_set } }`` returns a parameter set in JSON representation in terms of :need:`feat_req__config_mgmt__parameter_set_access` +- ``attribute InitialQualifierState InitialQualifierState readonly`` field provides qualifier state in terms of :need:`feat_req__config_mgmt__prm_initial_qualifier` +- ``broadcast LastUpdatedParameterSet { out { ParameterSetName last_updated_parameter_set } }`` event notifies users in case a parameter set has been changed (updated) according to :need:`feat_req__config_mgmt__parameter_modification`. + +``LoLa`` can be used for IPC communication as soon as methods get supported. + +``ConfigDaemon`` uses the file system via ``json library`` to write and read files which contain parameters. + +Plugin infrastructure may have further dependencies, like ``SOVD`` for ``Coding`` or persistent key-value storage. + +Backwards Compatibility +----------------------- + +No compatibility requirements imposed yet. + +Security Impact +--------------- + +``ConfigDaemon`` requires secpol abilities for IPC communication and file system accesses. + +Further specific mitigations shall be implemented by plugins depending on a kind of parameter. + +Safety Impact +------------- + +Safety related parameters shall be protected by specific integrity checks. Their result will be indicated towards user applications according to :need:`feat_req__config_mgmt__prm_set_qualifier` and :need:`feat_req__config_mgmt__prm_initial_qualifier`. + +A safety related user application is assumed to consider a parameter as unsafe if belonging qualifier is not in a ``Qualified`` state. + +This feature is rated with ASIL B. + +License Impact +-------------- + +[How could the copyright impacted by the license of the new contribution?] + +How to Teach This +----------------- + +Rejected Ideas +-------------- + +No ideas rejected yet. + +Open Issues +----------- + +No open issues identified yet. + +Footnotes +--------- diff --git a/docs/features/configuration/config_mgmt/requirements/index.rst b/docs/features/configuration/config_mgmt/requirements/index.rst new file mode 100644 index 0000000000..9966421b9a --- /dev/null +++ b/docs/features/configuration/config_mgmt/requirements/index.rst @@ -0,0 +1,158 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Requirements +############ + +Terms and definitions +===================== + +.. feat_req:: Term definition of Parameter + :id: feat_req__config_mgmt__term_parameter + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + An individual vehicle configuration property used for vehicle specific adaptations is called ``Parameter``. + +.. feat_req:: Term definition of Parameter Set + :id: feat_req__config_mgmt__term_parameter_set + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Group of Parameters which belong to the same functionality and share an integrity protection is called ``Parameter Set``. + +Data Housekeeping +================= + +.. feat_req:: Central housekeeping for Parameters + :id: feat_req__config_mgmt__central_housekeeping + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Configuration Management shall provide a central housekeeping for Parameters. + +.. feat_req:: Parameter relation to a Set + :id: feat_req__config_mgmt__parameter_set_relation + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Every Parameter shall be contained in exactly one Parameter Set. + +.. feat_req:: Parameter name uniqueness + :id: feat_req__config_mgmt__prm_name_unique + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Parameters names shall be unique for an ECU project. + +.. feat_req:: Parameter name uniqueness + :id: feat_req__config_mgmt__prm_set_name_unique + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Parameters Set names shall be unique for an ECU project. + +.. feat_req:: Parameter Set configuration contents + :id: feat_req__config_mgmt__prm_set_cfg_content + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Parameter Set configuration shall contain a mapping of Parameters to Parameter Sets, Parameter names and default values. + +.. feat_req:: Parameter Set configuration source + :id: feat_req__config_mgmt__prm_set_cfg_source + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Parameter Set configuration shall be determined solely by a read-only input source, deployed on the target. + +.. feat_req:: Parameter modification + :id: feat_req__config_mgmt__parameter_modification + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Parameter values shall be modifiable during runtime regarding modification procedure specific for a parameter kind. + +Parameter Provision +=================== + +.. feat_req:: Config provider interface + :id: feat_req__config_mgmt__provider_interface + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + Configuration Management shall provide a generic interface, independent of any Parameter definitions, for applications to access Parameters in read-only mode. + +.. feat_req:: Parameter Set access + :id: feat_req__config_mgmt__parameter_set_access + :reqtype: Functional + :security: YES + :safety: QM + :satisfies: stkh_req__functional_req__file_based + :status: valid + + A Parameter Set shall be accessible via interface using a key-value principle, where user application passes a Parameter Set name to the interface and its value is returned as result. + +Parameter Qualification +======================= + +.. feat_req:: Parameter Set qualifier + :id: feat_req__config_mgmt__prm_set_qualifier + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__functional_req__safe_config + :status: valid + + A Parameter Set shall contain a qualifier to indicate its integrity. + +.. feat_req:: Parameter initial qualifier + :id: feat_req__config_mgmt__prm_initial_qualifier + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__functional_req__safe_config + :status: valid + + There shall exist an overall qualifier for all Parameter Sets to indicate the state of integrity checks at the point of time of initial provision of parameters. diff --git a/docs/features/configuration/index.rst b/docs/features/configuration/index.rst new file mode 100644 index 0000000000..bc1c886554 --- /dev/null +++ b/docs/features/configuration/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Configuration +############# + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + */index From d8addc2490473cdb67f57b336f9411be5a73c8db Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Tue, 8 Jul 2025 11:36:48 +0200 Subject: [PATCH 061/102] Remove ASIL_D from process and artefacts Ref: Resolves #1145 --- .vscode/restructuredtext.code-snippets | 28 +++++++++--------- .../docs/requirements/mw-fr_logging_req.rst | 2 +- .../tracing/mw-fr_tracing.rst_tmp | 2 +- .../requirements/component_requirements.rst | 7 ++--- .../frameworks/feo/requirements/index.rst | 29 +++++++++---------- docs/requirements/stakeholder/index.rst | 19 ++++++++---- 6 files changed, 46 insertions(+), 41 deletions(-) diff --git a/.vscode/restructuredtext.code-snippets b/.vscode/restructuredtext.code-snippets index 9a3317f5f4..9e43d36b06 100644 --- a/.vscode/restructuredtext.code-snippets +++ b/.vscode/restructuredtext.code-snippets @@ -140,7 +140,7 @@ "body": [ ".. document:: $1", " :id: doc__$2", - " :safety: ${3|QM, ASIL_B, ASIL_D|}", + " :safety: ${3|QM, ASIL_B|}", " :status: ${4|valid, draft, invalid|}", "", " ${5}" @@ -154,7 +154,7 @@ " :id: stkh_req__$2", " :reqtype: ${3|Functional, Interface, Process, Legal, Non-Functional|}", " :security: ${4|YES, NO|}", - " :safety: ${5|QM, ASIL_B, ASIL_D|}", + " :safety: ${5|QM, ASIL_B|}", " :status: ${6|valid, invalid|}", " :rationale: ${7}", "", @@ -169,7 +169,7 @@ " :id: feat_req__$2", " :reqtype: ${3|Functional, Interface, Process, Legal, Non-Functional|}", " :security: ${4|YES, NO|}", - " :safety: ${5|QM, ASIL_B, ASIL_D|}", + " :safety: ${5|QM, ASIL_B|}", " :status: ${6|valid, invalid|}", " :satisfies: ${7}", "", @@ -184,7 +184,7 @@ " :id: comp_req__$2", " :reqtype: ${3|Functional, Interface, Process, Legal, Non-Functional|}", " :security: ${4|YES, NO|}", - " :safety: ${5|QM, ASIL_B, ASIL_D|}", + " :safety: ${5|QM, ASIL_B|}", " :status: ${6|valid, invalid|}", " :satisfies: ${7}", "", @@ -199,7 +199,7 @@ " :id: tool_req__$2", " :reqtype: ${3|Functional, Interface, Process, Legal, Non-Functional|}", " :security: ${4|YES, NO|}", - " :safety: ${5|QM, ASIL_B, ASIL_D|}", + " :safety: ${5|QM, ASIL_B|}", " :status: ${6|valid, invalid|}", " :satisfies: ${7}", "", @@ -214,7 +214,7 @@ " :id: aou_req__$2", " :reqtype: ${3|Functional, Interface, Process, Legal, Non-Functional|}", " :security: ${4|YES, NO|}", - " :safety: ${5|QM, ASIL_B, ASIL_D|}", + " :safety: ${5|QM, ASIL_B|}", " :status: ${6|valid, invalid|}", "", " ${7}" @@ -227,7 +227,7 @@ ".. feat_arc_sta:: $1", " :id: feat_arc_sta__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: feat_req__${6}", " :implements: feat_arc_int__${7}", @@ -247,7 +247,7 @@ ".. feat_arc_dyn:: $1", " :id: feat_arc_dyn__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: ${6}", "", @@ -261,7 +261,7 @@ ".. feat_arc_int:: $1", " :id: feat_arc_int__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: feat_req__${6}", "", @@ -280,7 +280,7 @@ ".. feat_arc_int_op:: $1", " :id: feat_arc_int_op__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :included_by: feat_arc_int__${6}", "", @@ -294,7 +294,7 @@ ".. comp_arc_sta:: $1", " :id: comp_arc_sta__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: comp_req__${6}", " :implements: comp_arc_int__${7}", @@ -315,7 +315,7 @@ ".. comp_arc_dyn:: $1", " :id: comp_arc_dyn__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: comp_req__${6}", "", @@ -329,7 +329,7 @@ ".. comp_arc_int:: $1", " :id: comp_arc_int__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :fulfils: comp_req__${6}", "", @@ -348,7 +348,7 @@ ".. comp_arc_int_op:: $1", " :id: comp_arc_int_op__$2", " :security: ${3|YES, NO|}", - " :safety: ${4|QM, ASIL_B, ASIL_D|}", + " :safety: ${4|QM, ASIL_B|}", " :status: ${5|valid, invalid|}", " :included_by: comp_arc_int__${6}", " :implements: feat_arc_int_op__${7}", diff --git a/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst b/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst index b135665722..6bf1c427ec 100644 --- a/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst +++ b/docs/features/analysis-infra/logging/docs/requirements/mw-fr_logging_req.rst @@ -471,7 +471,7 @@ Requirements :id: feat_req__logging__asil_support :reqtype: Non-Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: stkh_req__functional_req__safe_comput :status: valid diff --git a/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp b/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp index 766de45cf8..e7d1cf8c96 100644 --- a/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp +++ b/docs/features/analysis-infra/tracing/mw-fr_tracing.rst_tmp @@ -18,7 +18,7 @@ Feature Request .. document:: doc__tracing :id: doc__tracing :status: draft - :safety: ASIL_D + :safety: ASIL_B :tags: contribution_request, feature_request .. attention:: diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst index aa63eaa7b2..42568e7ac8 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst @@ -216,7 +216,7 @@ Component Requirements: feo :id: comp_req__feo__alive_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: feat_req__feo__alive_supervision :status: valid @@ -229,7 +229,7 @@ Component Requirements: feo :id: comp_req__feo__deadline_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: feat_req__feo__deadline_supervision :status: valid @@ -242,7 +242,7 @@ Component Requirements: feo :id: comp_req__feo__logical_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: feat_req__feo__logical_supervision :status: valid @@ -264,4 +264,3 @@ Component Requirements: feo This can be done e.g. via evaluation of floating point exceptions, checking of hardware registers or status information of the software platform. - diff --git a/docs/features/frameworks/feo/requirements/index.rst b/docs/features/frameworks/feo/requirements/index.rst index 3dbf9377f5..c70140c76c 100644 --- a/docs/features/frameworks/feo/requirements/index.rst +++ b/docs/features/frameworks/feo/requirements/index.rst @@ -166,37 +166,37 @@ Supervision :id: feat_req__feo__alive_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: stkh_req__dependability__safety_features, stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid - The framework shall provide the functionality to enable the reporting of - alive supervision checkpoint to an external health management system - (e.g. watchdog) + The framework shall provide the functionality to enable the reporting of + alive supervision checkpoint to an external health management system + (e.g. watchdog) .. feat_req:: Support of deadline supervision checkpoints :id: feat_req__feo__deadline_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: stkh_req__dependability__safety_features, stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid - The framework shall provide the functionality to enable the reporting of - deadline supervision checkpoints to an external health management system - (e.g. watchdog) + The framework shall provide the functionality to enable the reporting of + deadline supervision checkpoints to an external health management system + (e.g. watchdog) .. feat_req:: Support of logical supervision :id: feat_req__feo__logical_supervision :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :satisfies: stkh_req__dependability__safety_features, stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid - The framework shall provide the functionality to enable the reporting of - logical supervision checkpoints to an external health management system - (e.g. watchdog) + The framework shall provide the functionality to enable the reporting of + logical supervision checkpoints to an external health management system + (e.g. watchdog) .. feat_req:: Trustable computation :id: feat_req__feo__trustable_computation @@ -206,9 +206,8 @@ Supervision :satisfies: stkh_req__dependability__safety_features, stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid - The framework shall provide mechanisms to check after the computation of + The framework shall provide mechanisms to check after the computation of an Activity if the result is trustable. - This can be done e.g. via evaluation of floating point exceptions, + This can be done e.g. via evaluation of floating point exceptions, checking of hardware registers or status information of the software platform. - diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 3e5571085e..b91d9d2a3d 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -95,7 +95,7 @@ Functional requirements The software platform shall provide towards the applications a safe (ISO26262-2018) key/value store. - Note: This is part of 0.1 release and therefore can only support ASIL_B. Goal is ASIL_D. + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. .. stkh_req:: Safe Configuration :id: stkh_req__functional_req__safe_config @@ -106,19 +106,22 @@ Functional requirements :status: valid The platform shall support safe configuration. - Note: This is part of 0.1 release and therefore can only support ASIL_B. Goal is ASIL_D. + + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. .. stkh_req:: Safe Computation :id: stkh_req__functional_req__safe_comput :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :rationale: Safe systems require computations to be done in safe environments. :status: valid The platform shall support safe computation. + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. + .. stkh_req:: Base Libraries :id: stkh_req__functional_req__base_libraries @@ -236,14 +239,14 @@ Dependability The software platform shall support applications with an automotive safety integrity level up to ASIL-B. - Note: This is part of 0.1 release and therefore can only support ASIL_B. Goal is ASIL_D. + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. .. stkh_req:: Safety features :id: stkh_req__dependability__safety_features :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :rationale: tbd :status: valid @@ -261,6 +264,8 @@ Dependability * Power management integrated circuit (PMIC), external watchdog and voltage monitoring * Safe switch from engineering for field mode and back + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. + .. stkh_req:: Availability :id: stkh_req__dependability__availability @@ -483,12 +488,14 @@ Communication :id: stkh_req__communication__safe :reqtype: Functional :security: NO - :safety: ASIL_D + :safety: ASIL_B :rationale: Distributed safe systems often require communication to be safe. :status: valid The platform shall support safe communication. + Note: This is part of 0.5 release and therefore can only support ASIL_B. Goal is ASIL_D. + .. stkh_req:: Secure Communication :id: stkh_req__communication__secure From 88c2685c99bac64bbc53ea41cf5a1c914af95ac3 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Mon, 7 Jul 2025 14:34:58 +0200 Subject: [PATCH 062/102] Draft of platform release note for v0.5.0 Ref: Resolves #103 --- docs/score_releases/index.rst | 6 ++ docs/score_releases/platform_release_note.rst | 95 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 docs/score_releases/platform_release_note.rst diff --git a/docs/score_releases/index.rst b/docs/score_releases/index.rst index 4e525a9c1c..769ab115c5 100644 --- a/docs/score_releases/index.rst +++ b/docs/score_releases/index.rst @@ -124,3 +124,9 @@ SW Module List - _ - _ - _ + +.. toctree:: + :hidden: + :maxdepth: 2 + + platform_release_note diff --git a/docs/score_releases/platform_release_note.rst b/docs/score_releases/platform_release_note.rst new file mode 100644 index 0000000000..ceb61558a0 --- /dev/null +++ b/docs/score_releases/platform_release_note.rst @@ -0,0 +1,95 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Platform Release Notes +====================== + +.. note:: Document header + +.. document:: Platform Release Note + :id: doc__platform_release_note + :status: draft + :safety: ASIL_B + :realizes: wp__platform_sw_release_note + +| Platform Name: [S-CORE] +| Release Tag: v0.5.0 +| Origin Release Tag: none - first published release +| Release Commit Hash: <add hash> +| Release Date: YYYY-MM-DD +| +| Overview +| -------- +| +| This document provides an overview of the changes, improvements, and bug fixes included in the software platform release version v0.5.0 +| as compared to the platform origin release (which is usually the previous release). +| +| New Features +| ------------ +| +| - **Inter-process Communication**: Data transfer between processes on the same processor, based on shared memory. +| - **Fixed execution order framework**: Provides fixed and deterministic computation of tasks for applications. +| - **Logging**: Capturing detailed information about system events and application-level activities. +| - **Persistency Key-Value-Storage**: Structured permanent data for applications. +| +| Improvements +| ------------ +| +| - none, first published release +| +| Bug Fixes +| --------- +| +| - none, first published release +| +| Integrated Software Modules +| --------------------------- +| +| - **Communication**: (Version). Link to Software module release note. +| - **FEO**: (Version). Link to Software module release note. +| - **Logging**: (Version). Link to Software module release note. +| - **Tracing**: (Version). Link to Software module release note. +| - **Baselibs**: (Version). Link to Software module release note. +| - **OS**: (Version). Link to Software module release note (external module). +| - **Persistency**: (Version). Link to Software module release note. +| +| Associated Infrastructure Modules +| --------------------------------- +| +| - **process_description**: (Version). Process description of S-CORE. Link to release note? +| - **docs-as-code**: (Version). Tooling for linking and generation of documentation. Link to release note? +| - **tooling**: (Version). Provided tooling for S-CORE development. Link to release note? +| - **itf**: (Version). Integration Test Framework. Link to release note? +| +| Performed Verification +| ---------------------- +| This release note is based on the verification as documented in platform verification report +| <need link to add>. +| +| Known Issues +| ------------ +| +| - **Issue 1**: Brief description of the known issue. Justification regarding safety impact. +| - **Issue 2**: Brief description of the known issue. Justification regarding safety impact. +| - **Issue 3**: Brief description of the known issue. Justification regarding safety impact. +| +| Upgrade Instructions +| -------------------- +| +| 1. none, first published release. +| +| Contact Information +| ------------------- +| +| For any questions or support, please contact the *Project lead* or raise an issue/discussion. From 347ee35e932eeabbd09e077a1d95cdec08d27599 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> Date: Wed, 9 Jul 2025 13:53:59 +0200 Subject: [PATCH 063/102] f2f arch ws feedback added feedback from F2F Architecture Workshop - see Discussion 1247 --- .../score-diagnostics-distributed.drawio.svg | 6 ++-- docs/features/diagnostics/index.rst | 30 ++++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg b/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg index 4e97cc08a3..394e17a774 100644 --- a/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg +++ b/docs/features/diagnostics/_assets/score-diagnostics-distributed.drawio.svg @@ -1,4 +1,4 @@ -<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: #ffffff; background-color: light-dark(#ffffff, #121212);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1101px" height="762px" viewBox="-0.5 -0.5 1101 762" content="<mxfile scale="1" border="5"><diagram id="OtiXRZHrsBmRRigScPVE" name="Page-1">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</diagram></mxfile>"> +<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" style="background: #ffffff; background-color: light-dark(#ffffff, #121212);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1101px" height="762px" viewBox="-0.5 -0.5 1101 762" content="<mxfile scale="1" border="5"><diagram id="OtiXRZHrsBmRRigScPVE" name="Page-1">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</diagram></mxfile>"> <defs/> <rect fill="#ffffff" width="100%" height="100%" x="0" y="0" style="fill: light-dark(rgb(255, 255, 255), rgb(18, 18, 18));"/> <g> @@ -387,13 +387,13 @@ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 381px; margin-left: 265px;"> <div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; background-color: #ffffff; "> <div style="display: inline-block; font-size: 11px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); white-space: nowrap; "> - IPC + SOVD </div> </div> </div> </foreignObject> <text x="265" y="384" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="11px" text-anchor="middle"> - IPC + SOVD </text> </switch> </g> diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index b8d1f514ae..a2de45c05d 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -109,19 +109,23 @@ Fault Library - The interface needs to be specified further but will likely include: Fault ID (FID), time, ENUM fault type (like DLT ENUMs), optional meta data. - Fault lib is the base for activity specific, custom fault handling. - Can and should also be used by platform components to report faults. +- Potentially source of faults to be acted upon - e.g. by Health and Lifecycle Management. +- Also needs to enforce regulatory requirements for certain faults - e.g. emission relevant. - Decentral component. Diagnostic Fault Manager - Aggregates and manages diagnostic fault data from Fault libs across the system. - Provides centralized fault status to the SOVD Server. +- Not part of SOVD specification directly but a stack specific diagnostic implementation. - Interfaces with the Diagnostic DB (persistency) to store and retrieve data. - Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. - Central component. Diagnostic DB -- Stores static and runtime diagnostic data +- Potentially part of the Diagnostic Fault Manager process. +- Stores static and runtime diagnostic data. - Is considered in scope due to the domain specific data format but internally uses S-CORE::Persistency. - The data format needs to be specified further but will likely include: - Diagnostic Trouble Code (DTC): OEM specific code, relevant for end-user. @@ -135,12 +139,14 @@ SOVD Server - Central entry point for all diagnostic requests via SOVD. - Implements the SOVD API and dispatches requests to services, DB, and fault manager. - Manages authentication, configuration, and data access via IPC. +- SOVD communication via HTTP. - Central component. Service App - Is a base concept to extend the system with system-specific diagnostic services/routines (e.g. DTC clear, ECU reset, Flash Master). - Interfaces with the SOVD Server via IPC. +- Base for all specific service app implementations. - Central component derived from base service app. SOVD Gateway @@ -169,7 +175,7 @@ UDS2SOVD Proxy - Exposes selected SOVD functionality via UDS for backward-compatible testers. - Acts as a local translation layer between UDS clients and SOVD stack. - Configured via ODX files to define what is exposed. -- Central component and unique per system. +- Central component and unique per ECU (one per ECU or per System is possible). Out of scope components @@ -252,6 +258,9 @@ While diagnostics do not directly impact functional safety, a successful attack - for example by setting the system into a different state. Therefore, the overall security architecture must be revisited in detail to assess and mitigate potential risks introduced by the SOVD integration. +Since diagnostics is QM, even being able to breach into the SOVD stack must not violate safety guarantees. +This implies that session/mode-sensitive operations must be treated by the implementing apps in a way that doesn't impact safety. +The client lib(s) need to be developed with the same quality standards as safe components to ensure that and also provide FFI guarantees. Safety Impact ============= @@ -260,6 +269,8 @@ At this point in time no direct safety impact is foreseen. The expected ASIL lev Configuration Management could have a safety impact but is handled in another feature request and out of scope of this document. As pointed out in "Security Impact", a breach in the diagnostic system could theoretically effect safety-relevant functions - for example by setting the system into a different state. +The Fault Library could also have a safety impact if faults are propagated and act upon by other components +- for example Health and Lifecycle Management. License Impact @@ -293,11 +304,16 @@ Because no FOSS SOVD stack exists currently, it presents an opportunity for S-CO Open Issues =========== -- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase -- Investigate synergies between Configuration Manager and Diagnostic Fault Manager -- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 -- Check if Diagnostic Fault Manager component is required at all and could be removed (how would this impact dependency of Flib to persistency and access management?) -- Provide sequence diagram for a use case +- Interfacing concept with Autosar Adaptive Diagnostic Stack for mixed stacks and/or a transitional phase +- Evaluate publication of XML schemata to handle/convert ODX files as per ISO 22901 +- Provide sequence diagram for a use case +- Is the fault lib the source for faults to be acted upon by Health and Lifecycle Management? +- List regulatory requirements for certain faults/DTCs - e.g. emission relevant faults +- Provide recommended transition/migration scenario for UDS based components moving to SOVD +- Decide if SOVD communication inside the ECU uses IP based communication or an alternative such as UDS +- Decide on a common concept for Service Validation. How are Services Validated and where (Server vs. Service)? +- For Service Validation: How do Services access the state of the ECU and the state of certain apps? +- Add concept of how to interact with ECU State Management Footnotes From b0f2b1141d101316e9e0cc09d8486286ffcb905b Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Wed, 9 Jul 2025 13:23:24 +0200 Subject: [PATCH 064/102] Fix CfgMgt Plan audit actions Ref: Resolves #1392 --- .../config_management.rst | 56 ++++++++++++++++--- .../project_management.rst | 5 ++ 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/docs/platform_management_plan/config_management.rst b/docs/platform_management_plan/config_management.rst index 65dcc38bd1..ef85adfecc 100644 --- a/docs/platform_management_plan/config_management.rst +++ b/docs/platform_management_plan/config_management.rst @@ -50,17 +50,22 @@ note: for definition of "configuration items" check :need:`PROCESS_doc_concept__ Approach ++++++++ -.. gd_guidl:: Configuration - :id: gd_guidl__configuration - :status: valid - :complies: PROCESS_std_req__iso26262__support_741, PROCESS_std_req__iso26262__support_742, PROCESS_std_req__iso26262__support_743, PROCESS_std_req__iso26262__support_744, PROCESS_std_req__iso26262__support_745, PROCESS_std_req__aspice_40__SUP-8-BP1, PROCESS_std_req__aspice_40__SUP-8-BP3, PROCESS_std_req__aspice_40__SUP-8-BP4, PROCESS_std_req__aspice_40__SUP-8-BP5, PROCESS_std_req__aspice_40__SUP-8-BP8 +The steps below describe how configuration identification, retrieval, modification, branches and baselines, backup and recovery are organized. -Identification -^^^^^^^^^^^^^^ +Lifecycle +^^^^^^^^^ + +The configuration management of the S-CORE project is in place during the complete development lifecycle. +I.e. in Concept Phase, Development Phase and Maintenance. + + +Identification and Properties +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Each work product is identified by its sphinx-needs Id, this includes documents identified as such (see project documents list in :need:`doc__documentation_mgt_plan`). -Spinx-needs checks for Id duplicates. +Ids are checked for uniqueness, see <link PROCESS_gd_req__configuration__UID when merged>. +sphinx-needs is also used to document the work products properties/attributes defined in the process area descriptions. The work products are stored in text or code files (these are identified by their filenames) within GitHub repositories. There is one `platform repository <https://GitHub.com/eclipse-score/score/>`_ and one repository for each module. @@ -86,12 +91,13 @@ For release versioning rules check the respective section of release guideline. For other artefacts: these are pulled into S-CORE integration repository by forking to be handled as above. -Modification -^^^^^^^^^^^^ +Control and Modification +^^^^^^^^^^^^^^^^^^^^^^^^ Files or new work products contained in them are created in local branches by the :need:`Contributor <PROCESS_rl__contributor>` and shared for review and incorporation into the main branch via GitHub pull-requests, which are after their acceptance merged by the :need:`Committer <PROCESS_rl__committer>`. The same applies for changes in existing configuration items. +All modifications (differences between before and after) are documented in the pull-requests and are the main input to the pull-request reviews. See also :need:`doc__platform_change_management_plan`. For other artefacts modifications are controlled by the bazel build files which are also under configuration control. @@ -110,10 +116,18 @@ Git defines branches as a means of parallel development. In the S-CORE project t The "remote" branch is not "local" to the developer but resides on the "remote" GitHub server. +In S-CORE all configuration items are kept in GitHub, this means that there only needs to be one baseline for these +(and not multiple ones for each of the work products which are maintained in seperate tools). Baselines are created by using the GitHub "tag" function. The tag name shall correspond to the release branch name the tag is created, adding patch version and pre-release tag. See also :need:`doc__platform_release_management_plan`. +As described in "Identification and Properties" above, there are several repositories for the modules and the platform integration. +Baselines are created individually in these repositories, even a different version schema could be adopted. +In case of dependent repositories, the repository dependet upon on has to be baselined first, to be available +to refer to this baseline when integrating it. That means that for example a platform baseline also +documents the versions(baselines) of the modules the platform consists of. This can then also be seen in the platform release note. + Every change in the release repository is also taken over into the main branch. The module development team can decide how to ensure this (e.g. by development in main and cherrypick to release branch). @@ -123,3 +137,27 @@ Backup and Recovery Backup and recovery are covered by the Eclipse Foundation hosting the GitHub service for S-CORE. For the long term storage, additional measures are taken, see :need:`PROCESS_gd_req__workproducts_storage` + + +Status and Reporting +^^^^^^^^^^^^^^^^^^^^ + +Every work product defined in our proceses has a "status" attribute. These are used to communicate to all the stakeholders. +The main communication means is a document list containing all documents and workproducts including their status. +This list is typically part of the Documentation Management Plan :need:`doc__documentation_mgt_plan` as part of the Platform Management Plan, +as defined in :need:`PROCESS_gd_guidl__documentation`. +Completeness of the configuration items (within a baseline) is checked at least for every release +against the list of planned documents and workproducts, which is also part of the Documentation Management Plan. + + +Configuration Management Tooling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Almost all requirements of the standards towards configuration management can be covered by +standard versioning tooling of the Eclipse Foundation and of the S-CORE project +("structured text" identification of work products). +The respective tools used in the project are: + +* versioning: GitHub +* structured text: sphinx-needs +* CI build: Bazel diff --git a/docs/platform_management_plan/project_management.rst b/docs/platform_management_plan/project_management.rst index 06374343fe..e351faff7f 100644 --- a/docs/platform_management_plan/project_management.rst +++ b/docs/platform_management_plan/project_management.rst @@ -328,6 +328,11 @@ In the main *S-CORE* project we use milestones to mark important stages of the p You can find "up to date" overview of the release plan and milestones in the following section `S-CORE Releases <https://eclipse-score.github.io/score/score_releases/index.html>`_. +The users of the S-CORE platform need to adapt their planning to the milestones defined in the S-CORE project, +but they have always the possibility to takeover the development of a new feature, modifications and bugfixes +in their own development branch / fork and merge these improvements in the next or later releases +back into the S-CORE "main" line. + Planning process ---------------- Generally, every team is responsible for planning and managing of its backlog. From 16bd19f6aad24afbfcdf32033c28919a05fa450f Mon Sep 17 00:00:00 2001 From: Markus Hosch <markus.hosch@bmw.de> Date: Thu, 10 Jul 2025 09:27:31 +0200 Subject: [PATCH 065/102] Fix typo in rust_api_design.rst Signed-off-by: Markus Hosch <markus.hosch@bmw.de> --- docs/contribute/development/rust/rust_api_design.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contribute/development/rust/rust_api_design.rst b/docs/contribute/development/rust/rust_api_design.rst index a6baa49b0f..a55e9c8ae1 100644 --- a/docs/contribute/development/rust/rust_api_design.rst +++ b/docs/contribute/development/rust/rust_api_design.rst @@ -23,7 +23,7 @@ Preface ======= This document describes how public Rust APIs shall be designed in the S-CORE context. While these guidelines canalso be -beneficial for private APIs, following them also inside a single module is reommended to improve the code consistency +beneficial for private APIs, following them also inside a single module is recommended to improve the code consistency and also benefit from the perks it gives to the code. Writing Mockable Rust Code From 472525a1270cf4a853f385361cf38701140a7372 Mon Sep 17 00:00:00 2001 From: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> Date: Thu, 10 Jul 2025 11:11:15 +0300 Subject: [PATCH 066/102] infra: Handle stale feature_request PR (#1373) Close stale PR that have a specific feature request labeled after 90+10 days. Signed-off-by: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> --- .github/workflows/docs-cleanup.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/docs-cleanup.yml b/.github/workflows/docs-cleanup.yml index b9326b89e1..75a0c58bf3 100644 --- a/.github/workflows/docs-cleanup.yml +++ b/.github/workflows/docs-cleanup.yml @@ -27,10 +27,26 @@ jobs: pull-requests: write issues: write # Allow label creation steps: + - name: Close abandoned feature-request PRs + uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + only-pr-labels: feature_request + days-before-issue-stale: -1 # Override days-before-stale for issues only + days-before-issue-close: -1 # Override days-before-close for issues only + days-before-pr-stale: 90 # 30 days idle → stale + days-before-pr-close: 10 # close countdown + stale-pr-message: > + This feature request has been idle for 90 days. We'll auto-close it in 10 days unless there's new activity. + close-pr-label: autoclosed + operations-per-run: 90 + close-pr-message: "Auto-closing: no activity for 90 days. If this is still relevant, reopen or create a fresh PR." + - name: Close abandoned PRs uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} + exempt-pr-labels: feature_request # days-before-stale Idle number of days before marking issues/PRs stale (default: 60) # days-before-close Idle number of days before closing stale issues/PRs (default: 7) From 4458e4646e20a938e3594ae1b476fc937aef1de8 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Wed, 9 Jul 2025 16:24:28 +0200 Subject: [PATCH 067/102] FIx CfgMgt Plan audit actions - review updates Ref: Resolves #1392 --- .../config_management.rst | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/platform_management_plan/config_management.rst b/docs/platform_management_plan/config_management.rst index ef85adfecc..9a8eaaa94f 100644 --- a/docs/platform_management_plan/config_management.rst +++ b/docs/platform_management_plan/config_management.rst @@ -116,8 +116,8 @@ Git defines branches as a means of parallel development. In the S-CORE project t The "remote" branch is not "local" to the developer but resides on the "remote" GitHub server. -In S-CORE all configuration items are kept in GitHub, this means that there only needs to be one baseline for these -(and not multiple ones for each of the work products which are maintained in seperate tools). +In S-CORE all configuration items are kept in GitHub, this means that there only needs to be one baseline (per repository) for these +(and not multiple ones for each of the work products types which are maintained in separate tools). Baselines are created by using the GitHub "tag" function. The tag name shall correspond to the release branch name the tag is created, adding patch version and pre-release tag. See also :need:`doc__platform_release_management_plan`. @@ -126,7 +126,7 @@ As described in "Identification and Properties" above, there are several reposit Baselines are created individually in these repositories, even a different version schema could be adopted. In case of dependent repositories, the repository dependet upon on has to be baselined first, to be available to refer to this baseline when integrating it. That means that for example a platform baseline also -documents the versions(baselines) of the modules the platform consists of. This can then also be seen in the platform release note. +documents the versions (baselines) of the modules the platform consists of. This can then also be seen in the platform release note. Every change in the release repository is also taken over into the main branch. The module development team can decide how to ensure this (e.g. by development in main and cherrypick to release branch). @@ -142,12 +142,20 @@ For the long term storage, additional measures are taken, see :need:`PROCESS_gd_ Status and Reporting ^^^^^^^^^^^^^^^^^^^^ -Every work product defined in our proceses has a "status" attribute. These are used to communicate to all the stakeholders. -The main communication means is a document list containing all documents and workproducts including their status. +Work products defined in our proceses have "status" attributes. These are used to communicate to all the stakeholders. +The main communication means is a document list containing all documents including their status. This list is typically part of the Documentation Management Plan :need:`doc__documentation_mgt_plan` as part of the Platform Management Plan, as defined in :need:`PROCESS_gd_guidl__documentation`. Completeness of the configuration items (within a baseline) is checked at least for every release -against the list of planned documents and workproducts, which is also part of the Documentation Management Plan. +against the list of planned documents, which is also part of the Documentation Management Plan. +Note that work products consisting of several elements (documented as needs) will be collected in one file +which will form a document (e.g. there will be a document (doc__*) "feature xy requirements" and in it all the feature's requirements(feat_req__*)). +This applies to requirements, architeture, detailed design and safety analysis. +The files containing the source code and test code are not part of documents as above, +their status is implicitly "valid", as these are subject to code and test review before every merge. + +Also the used tools status and version is reported within a "tool list" which may be part of +the Documentation Management Plan or referenced from it (and also need to be checked for completeness). Configuration Management Tooling From 7ada4a67a902bfb6def54154b7d3d057bfd2b559 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> Date: Mon, 14 Jul 2025 13:16:12 +0200 Subject: [PATCH 068/102] Update docs/features/diagnostics/index.rst Co-authored-by: Markus Hosch <markus.hosch@gmx.net> Signed-off-by: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> --- docs/features/diagnostics/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index a2de45c05d..0ee9791054 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -172,7 +172,7 @@ Classic Diagnostic Adapter UDS2SOVD Proxy -- Exposes selected SOVD functionality via UDS for backward-compatible testers. +- Allows for the mapping of any UDS service to SOVD functionality in an arbitrary way for backward-compatible testers. - Acts as a local translation layer between UDS clients and SOVD stack. - Configured via ODX files to define what is exposed. - Central component and unique per ECU (one per ECU or per System is possible). From 821b15fda99ac05d4b007e625845199f5d920b08 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> Date: Mon, 14 Jul 2025 13:19:48 +0200 Subject: [PATCH 069/102] review feedback added added additional points to in scope components --- docs/features/diagnostics/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 0ee9791054..9604a47245 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -120,6 +120,7 @@ Diagnostic Fault Manager - Not part of SOVD specification directly but a stack specific diagnostic implementation. - Interfaces with the Diagnostic DB (persistency) to store and retrieve data. - Stores (persistently) central configuration (e.g. for debouncing thresholds) which can be loaded during startup by Fault libs. +- Implements the operation cycle concept (suppressing faults during phases where faults are to be expected). - Central component. Diagnostic DB @@ -168,6 +169,7 @@ Classic Diagnostic Adapter - Translates SOVD service calls to UDS commands. - Enables backward compatibility with legacy ECUs that only support UDS. - Configured via ODX files describing ECU-specific UDS expectations. +- UDS transport layer (e.g. DoIP or other vendor specific transports) shared with UDS2SOVD Proxy. - Central component and unique per system. UDS2SOVD Proxy @@ -175,6 +177,8 @@ UDS2SOVD Proxy - Allows for the mapping of any UDS service to SOVD functionality in an arbitrary way for backward-compatible testers. - Acts as a local translation layer between UDS clients and SOVD stack. - Configured via ODX files to define what is exposed. +- Implements the UDS session handling concept. +- UDS transport layer (e.g. DoIP or other vendor specific transports) shared with Classic Diagnostic Adapter. - Central component and unique per ECU (one per ECU or per System is possible). From f68a47ddd50aa2d7f8445526cf9db007aa9c8f62 Mon Sep 17 00:00:00 2001 From: Tim Kliefoth <tim.kliefoth@mercedes-benz.com> Date: Mon, 14 Jul 2025 14:13:39 +0200 Subject: [PATCH 070/102] fixed typo --- docs/features/diagnostics/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/diagnostics/index.rst b/docs/features/diagnostics/index.rst index 9604a47245..f04fc4d8b2 100644 --- a/docs/features/diagnostics/index.rst +++ b/docs/features/diagnostics/index.rst @@ -314,7 +314,7 @@ Open Issues - Is the fault lib the source for faults to be acted upon by Health and Lifecycle Management? - List regulatory requirements for certain faults/DTCs - e.g. emission relevant faults - Provide recommended transition/migration scenario for UDS based components moving to SOVD -- Decide if SOVD communication inside the ECU uses IP based communication or an alternative such as UDS +- Decide if SOVD communication inside the ECU uses IP based communication or an alternative such as UDS (Unix Domain Sockets) - Decide on a common concept for Service Validation. How are Services Validated and where (Server vs. Service)? - For Service Validation: How do Services access the state of the ECU and the state of certain apps? - Add concept of how to interact with ECU State Management From adef4eb058c577f5db640b3a9053f728b9c5eee8 Mon Sep 17 00:00:00 2001 From: "markus.schu" <markus.schu@accenture.com> Date: Thu, 3 Jul 2025 14:41:38 +0200 Subject: [PATCH 071/102] add initial pmp security management plan Resolves: #1366 --- docs/platform_management_plan/index.rst | 1 + .../security_management.rst | 454 ++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100644 docs/platform_management_plan/security_management.rst diff --git a/docs/platform_management_plan/index.rst b/docs/platform_management_plan/index.rst index 08eca73249..e3a23a4ced 100644 --- a/docs/platform_management_plan/index.rst +++ b/docs/platform_management_plan/index.rst @@ -30,6 +30,7 @@ Platform Management Plan project_management safety_management + security_management quality_management config_management tool_management diff --git a/docs/platform_management_plan/security_management.rst b/docs/platform_management_plan/security_management.rst new file mode 100644 index 0000000000..21d278d2d7 --- /dev/null +++ b/docs/platform_management_plan/security_management.rst @@ -0,0 +1,454 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. document:: Platform Security Plan + :id: doc__platform_security_plan + :status: draft + :safety: ASIL_B + :realizes: PROCESS_wp__platform_security_plan, PROCESS_wp__tailoring + :tags: platform_management + +Security management / Platform Security Plan +-------------------------------------------- + +WARNING: Security Management Process is NOT released yet, so links to Process_description using +`PROCESS_`... will not work yet, thus commented out. After releasing, document must be updated. + +Purpose ++++++++ + +The main purpose of the security plan is to: + +* adhere to ISO SAE 21434 where applicable for the project according to the defined tailoring + +And: + +* to define and assign the roles and responsibilities regarding security activities +* to define the tailored security activities, to provide the corresponding rationales for tailoring and to review the provided rationales +* to plan the security activities +* to coordinate and track the progress of security activities in accordance with the security plan +* to ensure a correct progression of the security activities throughout the security lifecycle +* to plan to create a comprehensible security package (collection of the security related work products) +* to judge whether the SW achieves security process conformance + +The term security is used here synonymously for the term cybersecurity as defined in ISO SAE 21434. + +Objectives and Scope +++++++++++++++++++++ + +Security Management Goals +^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Adherence to the ISO SAE 21434 according to the defined tailoring + +in detail + +* to plan all security related activities and work products +* to monitor and facilitate all activities +* to measure and report security status based on well-defined metrics + +Security Management Scope +^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is no deviation from the scope presented in the `S-CORE project page <https://eclipse-score.github.io/>`_ . +The platform and its components are developed, and integrated for an assumed technical system as platform and components Out of Context (OoC). +The development of the platform and its components follows the defined processes. +Responsibilities for development, implementation, integration and verification are also defined in the processes. + +Regarding the platform specifics: + +* SW in the project is either security relevant or not +* if relevant, security activities from a procedural point of view and SW are developed using additional rigour + +The SW platform functionality consists of features, which are based on a set of requirements and are developed in parallel. +These features are developed into SW components contained in "modules", which are another set of OoCs (initiated by a change request). +A template exists to guide this: need:`PROCESS_gd_temp__module_security_plan`. + +Tailoring +^^^^^^^^^ +Tailoring of security activities: + +* The tailoring is divided into project wide and module specific rules. +* Project wide tailoring is documented in this document - this is based on development of a platform OoC. +* Module OoC specific tailoring is documented in the module development Security Plans - this may be based on OoC specifics +* In case of a change request on an existing feature (i.e. a feature modification request), the subsequent security planning will be done based on an impact analysis. + +The following ISO SAE 21434 defined security work products are not relevant for the S-CORE SW platform development: + +Because Eclipse OSS project handbook applies and all content is public: :need:`PROCESS_std_wp__isosae21434__org_management_551`, + +Because these are in responsibility of the system integrator: :need:`PROCESS_std_wp__isosae21434__org_management_551`, +:need:`PROCESS_std_wp__isosae21434__org_management_555`, :need:`PROCESS_std_wp__isosae21434__prj_management_653`, +:need:`PROCESS_std_wp__isosae21434__assessment_15331`, :need:`PROCESS_std_wp__isosae21434__assessment_15332`, +:need:`PROCESS_std_wp__isosae21434__assessment_15431`, :need:`PROCESS_std_wp__isosae21434__assessment_15531` + +Summary: :need:`PROCESS_wp__tailoring` links to all the work products which are tailored out in the platform security plan, +to be able to demonstrate completeness in `REPLACE_external_standards` + + +Approach +++++++++ + +Security Culture +^^^^^^^^^^^^^^^^ + +The security of the project S-CORE is inherent. It relies on the personal dedication and integrity of every person who is involved in the project. +The security thinking in the project allows a questioning attitude and fosters the taking of responsibility. +Every participation, e.g. with the raise up of an improvement or by asking questions in the discussion section of GitHub is welcomed. +The processes, guidelines and templates define the organizational framework. +Adherence is verified by automated checks and manual inspections. +All the aspects of ISO SAE 21434 are directly implemented in the development process to ensure a proper communication and high understanding of security. +With continuous improvements, an integral aspect in all processes, we want to achieve excellence. + +Security Management Organization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is the project strategy to qualify the platform or components of the platform to the appropriate international standards and directives. +Therefore the project approach to facilitate a common culture regarding safety and security is part of our documentation. +The project will be under the Eclipse Foundation and so the `Eclipse Foundation Project Handbook: <https://www.eclipse.org/projects/handbook/>`_ applies. + +*Eclipse Roles* + +* `Contributors <https://www.eclipse.org/projects/handbook/#contributing-contributors>`_ can be everyone and we will not discourage the open source community from this. As the contributor cannot merge code (or any other work product) into the project's codebase, the security development competence of the contributor is irrelevant. +* `Committers <https://www.eclipse.org/projects/handbook/#contributing-committers>`_ play the main development role in the project, as only these are allowed to merge, so they are the ultimate responsible for the project's repository content. +* `Eclipse Foundation Security Team <https://www.eclipse.org/projects/handbook/#vulnerability-team>`_ provides help and advice to Eclipse projects on security issues and is the first point of contact for handling security vulnerabilities. + +*Project Roles* + +Roles are defined in every process and in a generic roles section. All those are matched to Eclipse roles. +Project role assignment is done in every feature development Security Plan. + +*Critical dependencies* + +The project has implemented a quality management system, aiming to be conform to ASPICE, as defined in the management system. +Continuous improvement is part to all processes. Improvements are handled in the scope of Quality Management. + +*Risk* + +Organization and management system has not a compliant mature level yet. + +*Skills* + +The main security related project roles are the project manager and the security manager and these also have to have the (Eclipse) committer role. +As defined in `Committer Training <https://www.eclipse.org/projects/training/>`_ the committers are elected in a meritocratic manner, meaning those have to show their skills and understanding of the project processes in several previous pull requests. + +As each project can adopt additional criteria for the committers election, we define the following: + +each committer has to prove his knowledge in security SW development by + +* an absolved training in ISO SAE 21434 (or equivalent standard, at least 16h of SW development specific training by a trusted training provider) OR +* by attending the projects's ISO SAE 21434 SW development training (given by a security team member) + +Additionally, the project repository shall be organized in a way that independent roles (to the technical solution) have to approve any pull request before it’s merged. + +In case of security related sections (e.g. a file containing feature requirements with a security relevance) the persons having approver rights need to have: +* One year of professional practice of security related SW development (or management) relevant for the section content + +The successful checking of committers and independent role skills is ensured by the security manager and documented in the role assignment document. +One important aspect to this is, that we ensure the identity of the committer by applying the GitHub digital signature mechanism. + +*Policies* +The `Eclipse Foundation Security Policy <https://www.eclipse.org/security/policy/>`_ apply for S-CORE. + + +Security Resources +^^^^^^^^^^^^^^^^^^ + +Security managers are elected by :need:`PROCESS_rl__project_lead` for all the S-CORE OoCs development. + +The security manager, supported by the project manager (i.e. the :need:`PROCESS_rl__technical_lead`), will ensure that +security activities are actively planned, developed, analyzed, verified and tested and managed throughout the life cycle of the project. +As all the implementation of security functions takes place within module development, there is a security manager appointed in the module's security plan. + +Resources and milestones are planned in Github Issues for all activities. +There are issue templates covering one feature development and for covering one development work product each. +Resource and milestone planning is done as defined in the :doc:`project_management` + +*Tools* + +The whole development and thus all work products are located in Github. The development is automated as much as possible and follows the defined processes. +Github issues are used as planning tool as well as security information (weakness, vulnerability) reporting and managing tool. +The issue types and issue types workflows are described in the platform management plan. +For security relevant issues types a "security" label is used. + +Reporting of vulnerabilities is supported here: `Eclipse general vulnerability tracker <https://gitlab.eclipse.org/security>`_. + +Security Management Communication +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To exchange general information and to clarify general topics the following communication channels are used: + +* Regular (online) meetings, at least every month. +* E-Mails +* Messenger Services e.g., Slack, Microsoft Teams, Github Notifications +* Ad hoc security related meetings are set up for clarification topics. + +*Reporting* + +The security management status is reported in the Technical Lead Circle Meeting which is defined in :need:`doc__project_mgt_plan`. +The status report is based on security plans work product lists (see below) and verification reports on platform and module level: + +* (tbc after release of process description) need:`PROCESS_wp__platform_security_plan` +* (tbc after release of process description) need:`PROCESS_wp__module_security_plan` +* :need:`PROCESS_wp__verification__platform_ver_report` +* :need:`PROCESS_wp__verification__module_ver_report` + +*Escalation* + +* Security Manager :need:`PROCESS_rl__security_manager` to steering committee documented in :need:`doc__project_mgt_plan`. +* :need:`PROCESS_rl__technical_lead` to :need:`PROCESS_rl__project_lead` + +Examples for valid escalation causes are: + +* Security issues cannot be resolved on module level or with the available resources. +* There are conflicting points of view between the Project Lead :need:`PROCESS_rl__project_lead`, Technical Lead :need:`PROCESS_rl__technical_lead`, Safety Manager :need:`PROCESS_rl__safety_manager`, Security Manager :need:`PROCESS_rl__security_manager` and the Quality Manager :need:`PROCESS_rl__quality_manager` + +Security Management Lifecycle +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The security lifecycle of the S-CORE project is initiated at the project set-up and driven and maintained by the security manager supported by the :need:`PROCESS_rl__process_community`. +Note that the Eclipse Foundation also defines `project phases <https://www.eclipse.org/projects/handbook/#starting-project-phases>`_. +Eclipse definition is more about the process maturity for the whole project, if we are in Mature Phase, we latest will have the project lifecycle as defined in our process description. +Nevertheless, Security Development and even Security Package release is independent from Mature and Incubation Phase as the completeness and appropriateness of the platform process and artifacts +is determined by Security Audit and not be Eclipse project reviews. + +Security Requirements +^^^^^^^^^^^^^^^^^^^^^ +Requirement Engineering is defined in the process description. See See :doc:`software_development`. + +The application of ISO SAE 21434 standards requirements is realized by defining process guidances and matching those to the ISO SAE 21434 requirements (see `REPLACE_processes_introduction`). + +Security Schedule +^^^^^^^^^^^^^^^^^ +The schedule is defined in section "Platform Security Plan" below, but also within each module security plan. See linked issues below and in need:`PROCESS_gd_temp__module_security_plan`. + +Security SW Development +^^^^^^^^^^^^^^^^^^^^^^^ +The SW development is defined in the project-wide software development plan. See :doc:`software_development`. + +Security Verification +^^^^^^^^^^^^^^^^^^^^^ +The platform management plan defines the :doc:`software_verification` + +Security Tool Management +^^^^^^^^^^^^^^^^^^^^^^^^ +The platform management plan defines :doc:`tool_management` + +Security Work Products +^^^^^^^^^^^^^^^^^^^^^^ +The work products relevant for a module development is defined within each module security management plan. See need:`PROCESS_gd_temp__module_security_plan`. +Generic project wide work products are defined below. + +Security Quality Criteria +^^^^^^^^^^^^^^^^^^^^^^^^^ +The platform management plan defines :doc:`quality_management` + +Platform Security Plan +++++++++++++++++++++++ + +Security Management SW Platform Work Products +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: SW Platform work products + :header-rows: 1 + + * - work product Id + - Link to process + - Process status + - Link to issue + - Link to WP + - WP status + + * - :need:`PROCESS_wp__training_path` + - n/a + - n/a + - n/a + - not open sourced + - to be shown to assessor + + * - :need:`PROCESS_wp__platform_mgmt` + - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` + - `#540 <https://github.com/eclipse-score/score/issues/540>`_ + - :doc:`index` + - :ndf:`copy('status', need_id='doc__platform_mgt_plan')` + + * - :need:`PROCESS_wp__qms_plan` + - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` + - `#316 <https://github.com/eclipse-score/score/issues/316>`_ + - :doc:`quality_management` + - not started + + * - need:`PROCESS_wp__platform_security_plan` + - need:`PROCESS_gd_guidl__security_plan_definitions` + - ndf:`copy('status', need_id='PROCESS_gd_guidl__security_plan_definitions')` + - `#TBD <https://github.com/eclipse-score/score/issues/381>`_ + - this document + - see above + + * - need:`PROCESS_wp__platform_security_package` + - need:`PROCESS_gd_guidl__security_package` + - ndf:`copy('status', need_id='PROCESS_gd_guidl__security_package')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__issue_track_system` + - :doc:`index` + - :ndf:`copy('status', need_id='doc__platform_mgt_plan')` + - n/a + - `Project issues <https://github.com/eclipse-score/score/issues>`_ + - established + + * - :need:`PROCESS_wp__process_definition` + - :need:`PROCESS_wf__def_app_process_definition` + - :ndf:`copy('status', need_id='PROCESS_wf__def_app_process_definition')` + - `Process community issues <https://github.com/orgs/eclipse-score/projects/7>`_ + - `REPLACE_process_description` + - <automated> + + * - :need:`PROCESS_wp__process_impr_report` + - :need:`PROCESS_wf__mon_ctrl_process_definition` + - :ndf:`copy('status', need_id='PROCESS_wf__mon_ctrl_process_definition')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__process_plan` + - :need:`PROCESS_wf__mon_ctrl_process_definition` + - :ndf:`copy('status', need_id='PROCESS_wf__mon_ctrl_process_definition')` + - `#232 <https://github.com/eclipse-score/score/issues/232>`_ + - `Process community issues <https://github.com/orgs/eclipse-score/projects/7>`_ + - <automated> + + * - need:`PROCESS_wp__fdr_reports_security` (platform Security Plan) + - need:`PROCESS_gd_chklst__security_plan` + - ndf:`copy('status', need_id='PROCESS_gd_chklst__security_plan')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - need:`PROCESS_wp__fdr_reports_security` (platform Security Package) + - need:`PROCESS_gd_chklst__security_package` + - ndf:`copy('status', need_id='PROCESS_gd_chklst__security_package')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - need:`PROCESS_wp__fdr_reports_security` (feature's Security Analyses) + - Security Analysis FDR tbd + - <automated> + - <Link to issue> + - <Link to WP> + - <automated> + + * - need:`PROCESS_wp__audit_report_security` + - performed by external experts + - n/a + - `#TBD1 <https://github.com/eclipse-score/score/issues/470>`_ + - <Link to WP> + - currently tailored out + + * - :need:`PROCESS_wp__platform_sw_build_config` + - :need:`doc__software_development_plan` + - :ndf:`copy('status', need_id='doc__software_development_plan')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - need:`PROCESS_wp__platform_security_manual` + - need:`PROCESS_gd_temp__security_manual` + - ndf:`copy('status', need_id='PROCESS_gd_temp__security_manual')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__platform_sw_release_note` + - :doc:`release_management` + - not started + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__verification__platform_ver_report` + - :need:`PROCESS_gd_temp__mod_ver_report` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__mod_ver_report')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__requirements__stkh` + - :need:`PROCESS_gd_temp__req__stkh_req` + - :ndf:`copy('status', need_id='PROCESS_gd_temp__req__stkh_req')` + - n/a (done already) + - :ref:`stakeholder_requirements` + - <automated> + + * - :need:`PROCESS_wp__sw_development_plan` + - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` + - <Link to issue> + - :doc:`software_development` + - not started + + * - :need:`PROCESS_wp__verification__plan` + - :need:`PROCESS_wf__platform__cr_mt_platform_mgmt_plan` + - :ndf:`copy('status', need_id='PROCESS_wf__platform__cr_mt_platform_mgmt_plan')` + - <Link to issue> + - :doc:`software_verification` + - not started + + * - :need:`PROCESS_wp__tool_verification_report` + - :doc:`tool_management` + - not started + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__tailoring` (generic) + - need:`PROCESS_gd_guidl__security_plan_definitions` + - ndf:`copy('status', need_id='PROCESS_gd_guidl__security_plan_definitions')` + - `#TBD2 <https://github.com/eclipse-score/score/issues/307>`_ + - `REPLACEstandard_iso26262` & :need:`doc__platform_safety_plan` + - valid + + * - need:`PROCESS_wp__sw_platform_sbom` + - need:`PROCESS_wf__cr_mt_security_sbom` + - not started + - <Link to issue> + - <Link to WP> + - <automated> + +Security Management Feature Specific Work Products +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See feature tree documents (created by using need:`PROCESS_gd_temp__feature_security_wp`): + +<link to document for every feature> + +Security Work Products Status Charts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. needtable:: + :style: table + :columns: title;id;status;realizes + :colwidths: 25,25,25,25 + :sort: title + + results = [] + + for need in needs.filter_types(["document"]): + if need and "platform_management" in need["tags"]: + results.append(need) From 70341cd9bfb25ea7ab402cbfa5037105f35a93ad Mon Sep 17 00:00:00 2001 From: "markus.schu" <markus.schu@accenture.com> Date: Fri, 11 Jul 2025 09:13:44 +0200 Subject: [PATCH 072/102] add score tools folder Add docs-as-code evaulation report Update Evaluation workflow in Tool Management Plan Resolves: #1142 --- docs/index.rst | 1 + ...core_tool_management_evaluation.drawio.svg | 2 +- .../tool_management.rst | 21 +- .../_assets/doc_as_code.drawio.svg | 4 + docs/score_tools/doc_as_code.rst | 181 ++++++++++++++++++ docs/score_tools/index.rst | 32 ++++ 6 files changed, 220 insertions(+), 21 deletions(-) create mode 100644 docs/score_tools/_assets/doc_as_code.drawio.svg create mode 100644 docs/score_tools/doc_as_code.rst create mode 100644 docs/score_tools/index.rst diff --git a/docs/index.rst b/docs/index.rst index bf21ee074b..2d0c18b49f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -135,5 +135,6 @@ Project structure and processes modules/index contribute/index Releases <score_releases/index.rst> + Tools <score_tools/index.rst> PMP <platform_management_plan/index.rst> Eclipse <https://projects.eclipse.org/projects/automotive.score> diff --git a/docs/platform_management_plan/_assets/score_tool_management_evaluation.drawio.svg b/docs/platform_management_plan/_assets/score_tool_management_evaluation.drawio.svg index 5399b552da..b00c73d209 100644 --- a/docs/platform_management_plan/_assets/score_tool_management_evaluation.drawio.svg +++ b/docs/platform_management_plan/_assets/score_tool_management_evaluation.drawio.svg @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Do not edit this file with editors other than diagrams.net --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1051px" height="411px" viewBox="-0.5 -0.5 1051 411" content="<mxfile host="Electron" modified="2025-04-30T12:17:06.197Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="P5PwkyqmTQRKHV01u1Pa" version="20.3.0" type="device"><diagram id="0w90vh-N4AjfHz9zUi27" name="Model">5Vpdc5s4FP01nmkf2kES2Pgxdr46k9101502fZRB2GowokJO4v76SiCMkbCTrrFJ1uQh0kUS8r1HR0cXemi8eLriOJ3/xUIS96ATPvXQeQ9Ct+9C+U9ZVoUFgEFhmHEaalNlmNBfRBsdbV3SkGS1hoKxWNC0bgxYkpBA1GyYc/ZYbxaxuP7UFM+IZZgEOLat32go5oXV95zKfk3obF4+GTj6zgKXjbUhm+OQPW6Y0EUPjTljoigtnsYkVs4r/VL0u9xydz0xThLxkg73n8dXZPUj+pl85fQOsbtocf8B9othHnC81L+4B/uxHHA05bI0U6XXb5kIkspfgbSnxaoMH2fLJCTKA45s9jingkxSHKi7jxKw0jYXi1jWgCxGNI7HLGY874uiYTRQXUeZ4OyebNxBfTRE6g6O6SyRtphExcRyXxIuyNPWKIF17OWiIWxBBF/JJrrDB4BcDZhyxaCBNjxWAPRK23wTfKURa9DP1sNXuJAFDY0/gYlnwUS7/E3CpT1Li3Cb4sAPURPcIHJdbxNuvIh5O3hzBgbeALLxhpwGvEF0MLy52/AGuo74a7O0SXie+lN2lohNusuvJmT28+tYRNgETOgdFZj2DkNCqRd0lXExZzOW4Piiso7qIana3DCW6kD8IEKstPjBS8HqYSqeqR6025dyXmzJA7Jj/qWEwnxGxK4F2BwbTmIs6EN9Hq07GcAuvCx9yVd3qv9Hr6x+18PllfOnWm2lax1EBzh7hifvesY5Xm00SBlNRLYx8mdlqK1IaKxI6Pt1zfl8F9B3dncZot09ZKGYeQWwtQv2wJy14XyRxwxp+Uo4jWgg/coSWf2XpBJbNhG/O78dv7dgKzV/qoohC5aLHA7PUfK0gPHNtL7496RSzwqc61tUClxkU6l/KCb13ziT7suQ2xYMdIxQua4RgoIedEcjCm2sBNBFZCr2rXFvRcWHZ194LPbdTxpbRGVrwDlbTJfZ82TTCrdAU6Y1cYvfoNIORi324eGckUxnjtQksKpgRed0IZ3TQOc512c4IkJO5zIjwZJTWUSXlrOl60Tdq6UWDqQLiRTKI+VguYPEZ/rGgoZhsWpIRn/haT6UArPegeW43qjnnaux5ELJijUDLAGesIQYKl6b2gnswDMC63j2ptGkv03Gai2ydhri+8XkhEJSSqEqJJ4dkqaIHOxAZOcP/749oYBAZKwRBG3yc48ZkKEVEC1kxyyJaEgSuRdA54Y85In6d1/GN+976GxHrqE0XH+6ui6NcmbTrSmI/3G0fSParm9nJEDTXncwRgReF2qtRdVVvuh5PiXRyqG3TcX9xwdo62jrOs8chhsm5xzhNAw7OQN0gSow3BNV+61ex2Jry/FHVfND82VA52IeIMtF41y6iznZEPDOVNXsbSzlcqeTu04oHx4SQQJVPCUZb3EOdBpSP+ioe5Z9QDspGT/0jZA0icajqvjyo4y3y/f9l/J9p3Tf9LWF6fc4pmlmoq+n3sCqaxtU28ClPF2aXDFAFjCbqOJwL4Lfepp4b32xRRgOLClZZgKOlSa2D5o7sLzh3PKdCEnCicDCRHoN3a3A2jc1zVrfd4bqF8i+1+E7AIF55O3cedByXksZjpvbb6ed4Bi6ry6/AW35f0oJRt/MODUlfI+aX4RbE4z/LKXTa6/Kfy4pVyevU4nWwHzN3kSWoOnTzf8QLlmtPh4udvXqE2x08Rs=</diagram></mxfile>"><defs/><g><rect x="260" y="240" width="570" height="170" fill="#f9f7ed" stroke="#36393d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 568px; height: 1px; padding-top: 325px; margin-left: 262px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Step 3</div></div></div></foreignObject><text x="262" y="329" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">Step 3...</text></switch></g><rect x="530" y="0" width="300" height="230" fill="#bac8d3" stroke="#23445d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 298px; height: 1px; padding-top: 115px; margin-left: 530px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Step 2<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="828" y="119" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">Step 2...</text></switch></g><rect x="260" y="0" width="250" height="230" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 248px; height: 1px; padding-top: 115px; margin-left: 262px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Step 1<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="262" y="119" fill="#333333" font-family="Helvetica" font-size="12px">Step 1...</text></switch></g><path d="M 223 158 L 353.63 158" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358.88 158 L 351.88 161.5 L 353.63 158 L 351.88 154.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 223 158 L 280 158 L 280 30 L 670 30 L 670 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 670 116.88 L 666.5 109.88 L 670 111.63 L 673.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 80 118 L 223 118 L 223 186 Q 187.25 164.4 151.5 186 Q 115.75 207.6 80 186 L 80 130 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 141px; height: 1px; padding-top: 146px; margin-left: 81px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tool Verification Report<br />(DOC)</div></div></div></foreignObject><text x="152" y="150" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Verification Report...</text></switch></g><path d="M 400 198 L 400 303.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 400 308.88 L 396.5 301.88 L 400 303.63 L 403.5 301.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 440 158 L 623.63 158" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 628.88 158 L 621.88 161.5 L 623.63 158 L 621.88 154.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 400 118 L 440 158 L 400 198 L 360 158 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="325" y="75" width="150" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 95px; margin-left: 400px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Does tool has an impact<br />on safety/security?</div></div></div></foreignObject><text x="400" y="99" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Does tool has an impact...</text></switch></g><rect x="440" y="125" width="50" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 140px; margin-left: 465px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">YES</div></div></div></foreignObject><text x="465" y="144" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">YES</text></switch></g><rect x="365" y="198" width="40" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 213px; margin-left: 385px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">NO</div></div></div></foreignObject><text x="385" y="217" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">NO</text></switch></g><rect x="315" y="350" width="180" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 370px; margin-left: 405px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Confidence Level (TCL):<br /><b>HIGH</b></div></div></div></foreignObject><text x="405" y="374" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Confidence Level (TCL):...</text></switch></g><path d="M 670 198 L 670 270 L 400 270 L 400 303.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 400 308.88 L 396.5 301.88 L 400 303.63 L 403.5 301.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 710 158 L 745 158 L 745 303.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 745 308.88 L 741.5 301.88 L 745 303.63 L 748.5 301.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 670 118 L 710 158 L 670 198 L 630 158 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="670" y="78" width="130" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 98px; margin-left: 735px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Can the impact be <br />prevented/detected?</div></div></div></foreignObject><text x="735" y="102" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Can the impact be...</text></switch></g><rect x="620" y="198" width="50" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 213px; margin-left: 645px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">YES</div></div></div></foreignObject><text x="645" y="217" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">YES</text></switch></g><path d="M 30 158 L 73.63 158" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 78.88 158 L 71.88 161.5 L 73.63 158 L 71.88 154.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="15" cy="158" rx="15" ry="15" fill="#000000" stroke="none" pointer-events="all"/><path d="M 760 325 L 863.63 325" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 868.88 325 L 861.88 328.5 L 863.63 325 L 861.88 321.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="745" cy="325" rx="11" ry="11" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="745" cy="325" rx="15" ry="15" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="400" cy="325" rx="11" ry="11" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="400" cy="325" rx="15" ry="15" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><rect x="655" y="350" width="180" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 370px; margin-left: 745px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Confidence Level (TCL):<br /><b>LOW</b></div></div></div></foreignObject><text x="745" y="374" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Confidence Level (TCL):...</text></switch></g><rect x="715" y="125" width="40" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 140px; margin-left: 735px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">NO</div></div></div></foreignObject><text x="735" y="144" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">NO</text></switch></g><rect x="880" y="310" width="170" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 325px; margin-left: 965px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Qualification Required</div></div></div></foreignObject><text x="965" y="329" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Qualification Required</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1051px" height="395px" viewBox="-0.5 -0.5 1051 395" content="<mxfile host="Electron" modified="2025-07-11T06:54:33.294Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="Or3JXRXyUnZDPDCOGNJv" version="20.3.0" type="device"><diagram id="0w90vh-N4AjfHz9zUi27" name="Model">5Vpdc5s4FP01nmkfsgMS2PgxtvOxM95Nd91p00cZhFEDiAo5jvvrKxkRg4TtNMEfqZ2HSFcSiHuOro4udOAwebphKIv+oQGOO8AKnjpw1AEAQs8W/6RlWVguHMstLDNGgsJmrw0T8hMro6WscxLgvNaRUxpzktWNPk1T7POaDTFGF/VuIY3rd83QDBuGiY9i0/qVBDwqrJ5rre23mMyi8s62pVoSVHZWhjxCAV1UTPCqA4eMUl6UkqchjqX3Sr8U4643tD5PjOGUv2TAw6fhDV5+D3+kXxi5h/Q+TB4uQLe4zCOK5+qJO6AbiwsOpkyUZrJ0+pYJx5l4Cqg8zZclfIzO0wBLD1ii2yIiHE8y5MvWhWCssEU8iUXNFsWQxPGQxpStxsKwH/bk0EHOGX3AlRbYhX0oW1BMZqmwxTgsJqZDolB6xIzjp4pJQXSDaYI5W4ouqvXCho4ijFoyNuwpw2JNQLe0RVXylUakSD97vvyaF6KgqPE7NHH3RhMF3buk3WstLZJ0inwvgE0kBdBx3CpJWcGUdlhq9TSW2n2TpdA6LEudfbPUPjZz/hjehq78k3aa8mpoXf2a+Nxd/Q4VdJvoDNyD0tnczXAgtImqUsYjOqMpiq/W1kEdknWfMaWZAuI75nyphBaac1qHaaM3czpnPt4y3VKdITbDfNsqLfrJZ9mKDcMx4uSxrsNad3LJlXXI+CzkpbB8wYyExBdToKmo/o8z4U1zUXwY3Q0/GkAJrZfJYkD9ebLy5K7lMS2AG093AvE7tHaBRmvgeAatbQeatPb2xWrvfbG6dbaqoZ8oEVOpQAUsDSrH0SAoVpYaqKHwPJM3rAT7GMgIQNjyXo1fVb7Jyl9uWR09VRtHS1V7M6I741R5Aj2RQAUatI2+H0c0mc7z3cGmldgC9C2zKbZ4DTvm3kKLKf9GFOcqYyAngWQFyXBOEuGchnC+ivU5CjEX07nOsT9nRBThteFs4Sde92qpS3zhVSxEy0B6U+wg8aVqSEgQFKsG5+Qnmq4uJcmcyTW98oY76LgjeS2xUPJizdiGGEppijVFpUztANtzNWDLnE1102jSQnrEag1Z8/j57WpyRpDYXX2tuSYkTYjAfSFi5o3+vTsjQADU1ggEZvBzDglI3wBECdkhTUMS4FTsBcAa48dVhvbD5+H4Ywdebjn3lYbbv29uS6OY2XTjcfAPRtvT0HY883RoN+11e4uItnsMtfZ61VWqqd3Hw9ZlV+uK+5IxtKx0U2TdfKs+1O9kabn6F0yuPkQUimm0egYARzkDHIBVdr9tVr1t9VpGtDYcf1A139fTuUcX8zY0XDRcSXce4YqAt6ayZm5jGRM7ndh1AnHzAHPsy+I5yXgj5gCrIfUDD7pnmQe0s5LxfU+DpEk0HlTF2713Fu+7L433pxXum96y636PY5LlOvs68h2a/G2iahu8FKdLPVb0oEHMplCxN2KCd5Ymbl9fbBCGPUNKlpmAQ6WJzYPmFi5XnFu+E8FpMOGI60yvsbsVWnu6pnnW90dj9Qtk32n4zga2fuQ9uvOA4byWMhzju6/nneDoOyeX3wCm/D+nBKOnZ5yaEr4HzS+CjQnG/+bC6bVX5T/mhMmT17mg1dNfszcFS7vpk71XwCWq649Gi119/e0tvPoF</diagram></mxfile>"><defs/><g><rect x="260" y="224" width="570" height="170" fill="#f9f7ed" stroke="#36393d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 568px; height: 1px; padding-top: 309px; margin-left: 262px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />Step 3</div></div></div></foreignObject><text x="262" y="313" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">Step 3...</text></switch></g><rect x="530" y="44" width="300" height="170" fill="#bac8d3" stroke="#23445d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 298px; height: 1px; padding-top: 129px; margin-left: 530px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br />Step 2<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="828" y="133" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="end">Step 2...</text></switch></g><rect x="260" y="44" width="250" height="170" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 248px; height: 1px; padding-top: 129px; margin-left: 262px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br />Step 1<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="262" y="133" fill="#333333" font-family="Helvetica" font-size="12px">Step 1...</text></switch></g><path d="M 223 142 L 353.63 142" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358.88 142 L 351.88 145.5 L 353.63 142 L 351.88 138.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 80 102 L 223 102 L 223 170 Q 187.25 148.4 151.5 170 Q 115.75 191.6 80 170 L 80 114 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 141px; height: 1px; padding-top: 130px; margin-left: 81px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Tool Verification Report<br />(DOC)</div></div></div></foreignObject><text x="152" y="134" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Verification Report...</text></switch></g><path d="M 400 182 L 400 287.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 400 292.88 L 396.5 285.88 L 400 287.63 L 403.5 285.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 440 142 L 623.63 142" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 628.88 142 L 621.88 145.5 L 623.63 142 L 621.88 138.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 400 102 L 440 142 L 400 182 L 360 142 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="325" y="59" width="150" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 79px; margin-left: 400px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Does tool has an impact<br />on safety/security?</div></div></div></foreignObject><text x="400" y="83" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Does tool has an impact...</text></switch></g><rect x="440" y="109" width="50" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 124px; margin-left: 465px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">YES</div></div></div></foreignObject><text x="465" y="128" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">YES</text></switch></g><rect x="365" y="182" width="40" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 197px; margin-left: 385px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">NO</div></div></div></foreignObject><text x="385" y="201" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">NO</text></switch></g><rect x="315" y="334" width="180" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 354px; margin-left: 405px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Confidence Level (TCL):<br /><b>HIGH</b></div></div></div></foreignObject><text x="405" y="358" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Confidence Level (TCL):...</text></switch></g><path d="M 670.03 181.97 L 670.03 254.03 L 400.03 254.03 L 400 287.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 400 292.88 L 396.51 285.88 L 400 287.63 L 403.51 285.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 709.97 142.03 L 745 142.03 L 745 287.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 745 292.88 L 741.5 285.88 L 745 287.63 L 748.5 285.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 670 102 L 710 142 L 670 182 L 630 142 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="670" y="62" width="130" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 82px; margin-left: 735px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Can the impact be <br />prevented/detected?</div></div></div></foreignObject><text x="735" y="86" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Can the impact be...</text></switch></g><rect x="620" y="182" width="50" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 197px; margin-left: 645px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">YES</div></div></div></foreignObject><text x="645" y="201" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">YES</text></switch></g><path d="M 30 142 L 73.63 142" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 78.88 142 L 71.88 145.5 L 73.63 142 L 71.88 138.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="15" cy="142" rx="15" ry="15" fill="#000000" stroke="none" pointer-events="all"/><path d="M 760 309 L 863.63 309" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 868.88 309 L 861.88 312.5 L 863.63 309 L 861.88 305.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="745" cy="309" rx="11" ry="11" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="745" cy="309" rx="15" ry="15" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="400" cy="309" rx="11" ry="11" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" pointer-events="all"/><ellipse cx="400" cy="309" rx="15" ry="15" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><rect x="655" y="334" width="180" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 354px; margin-left: 745px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Confidence Level (TCL):<br /><b>LOW</b></div></div></div></foreignObject><text x="745" y="358" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Confidence Level (TCL):...</text></switch></g><rect x="715" y="109" width="40" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 124px; margin-left: 735px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">NO</div></div></div></foreignObject><text x="735" y="128" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">NO</text></switch></g><rect x="880" y="294" width="170" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 309px; margin-left: 965px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Tool Qualification Required</div></div></div></foreignObject><text x="965" y="313" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Tool Qualification Required</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/docs/platform_management_plan/tool_management.rst b/docs/platform_management_plan/tool_management.rst index 6caf6b447e..90d51504f4 100644 --- a/docs/platform_management_plan/tool_management.rst +++ b/docs/platform_management_plan/tool_management.rst @@ -169,23 +169,4 @@ development, as they are not used: Tool List ^^^^^^^^^ -.. _platform_tool_list: - -.. list-table:: SW Platform tool overview - :header-rows: 1 - - * - tool Id - - tool name - - tool status - - tool TCL - - Link to tool evaluation issue (GitHub Issue) - - Link to tool qualification issue (GitHub Issue) - - Link to verification report (contains version, use cases, link to manuals, etc.) - - * - # - - sphinx-needs - - draft <automated> - - not evaluated yet - - <Link to issue> - - <Link to issue> - - <Link to tool verification report> +The S-CORE tools overview can be found here: :ref:`tools` diff --git a/docs/score_tools/_assets/doc_as_code.drawio.svg b/docs/score_tools/_assets/doc_as_code.drawio.svg new file mode 100644 index 0000000000..170180712c --- /dev/null +++ b/docs/score_tools/_assets/doc_as_code.drawio.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than diagrams.net --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="481px" height="203px" viewBox="-0.5 -0.5 481 203" content="<mxfile host="Electron" modified="2025-07-11T06:29:29.568Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="reSQZugyyMc2qxi1g6Wz" version="20.3.0" type="device"><diagram id="oTWkkxlc3c0ThQJxZTR6" name="Page-1">1Vdbb5swFP41PBZhGE3yuJC01dRJk7Jpl5fKwS54MxxmDk3SXz8bzC1sXTstW5uX4M/HGH8XY5wgyvaXihbpW2BcOr7H9k6wcnyf+P65/jPIoUXmfoMkSjCL9cBG3HMLehatBOPlqBABJIpiDMaQ5zzGEUaVgt247BbkeNaCJnwCbGIqp+hHwTBt0Hno9fgVF0nazkw825PRttgCZUoZ7AZQsHaCSAFgc5XtIy4Ney0vzbiLX/R2D6Z4jo8ZwBPvJk29+836zeur72Lz/ssH/4zM7cPhoV0xZ5oA2wSFKSSQU7nu0aWCKmfc3NbTrb7mGqDQINHgV454sGrSCkFDKWbS9t5CjhFIUPWMgVf/ND5dkl1lCZWK+UPrsD5DqhKODxXOmkKzysEUlrJLDhlHddAFikuK4m5sA2rdlHR1PeH6wnL+FP7tc99RWdmpXFWiY7S8cDNmLCukDsCxStpNhblkEFdZTddylwrkm4LWRO10HsekbxvVrrd/rMIdV8j3D7JmexdtCmzsX9nmro8QaXORDuIz907EcxfCl+7z2WN9vnhePp9NfL6C+IyWZ5F+Z0y06Zknvzf2CX1MvPnYyOEjjXx+KiO3ug43jJqLl7lRkI6pZ7NT+P9jp9AMqsMnM94N2+bnYd9qb2/etA629fd3mO6U9cLepJ33+mBMhIQKpch51J0VDVWMlmknnXGu0Ke/a7rl8h2UAgXkum8LiJANCl5LkZgONAIvqW3Fmm6uxtK2Acz2iTkju3RXBq4+rt6K5EZVtX10cuVAxVm4iMzKl3oAE7xXOIecnziPhPiuH44iSWbTTIahG05DOfNPJW4wETeqGawUrRU6VlovF8cyTCQ6VjITjDVh5qW4p9v6VobWAkSO9YrCpROuzL10fssmyrXCqOAbPxZpoOm/0O3oRUUWZCLa4if7aPD0fVQ3+6+Wum/w8ResfwA=</diagram></mxfile>"><defs/><g><path d="M 120 40 L 173.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 40 L 171.88 43.5 L 173.63 40 L 171.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 0 L 120 0 L 120 68 Q 90 46.4 60 68 Q 30 89.6 0 68 L 0 12 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 28px; margin-left: 1px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">.rst /.md files</div></div></div></foreignObject><text x="60" y="32" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">.rst /.md files</text></switch></g><path d="M 300 40 L 353.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358.88 40 L 351.88 43.5 L 353.63 40 L 351.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="180" y="10" width="120" height="60" rx="9" ry="9" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 40px; margin-left: 181px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Doc-as-Code</div></div></div></foreignObject><text x="240" y="44" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Doc-as-Code</text></switch></g><path d="M 360 0 L 480 0 L 480 68 Q 450 46.4 420 68 Q 390 89.6 360 68 L 360 12 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 28px; margin-left: 361px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">.html files</div></div></div></foreignObject><text x="420" y="32" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">.html files</text></switch></g><path d="M 240 130 L 240 100 L 240 76.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 240 71.12 L 243.5 78.12 L 240 76.37 L 236.5 78.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 267.75 202 L 212.25 202 L 212.25 130 L 229.57 130 L 238.11 137.91 L 267.75 137.91 Z" fill="#759c3e" stroke="none" pointer-events="all"/><path d="M 267.75 158.82 L 238.11 158.82 L 229.57 150.91 L 212.25 150.91 L 212.25 148.65 L 229.57 148.65 L 238.11 156.56 L 267.75 156.56 Z M 267.75 179.88 L 238.11 179.88 L 229.57 171.97 L 212.25 171.97 L 212.25 169.73 L 229.57 169.73 L 238.11 177.64 L 267.75 177.64 Z M 267.75 202 L 212.25 202 L 212.25 199.18 L 267.75 199.18 Z" fill-opacity="0.3" fill="#000000" stroke="none" pointer-events="all"/><rect x="212.25" y="130" width="0" height="0" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 256.37 174.13 L 250.46 168.25 L 253.38 165.33 L 256.43 168.34 L 262.95 161.86 L 265.83 164.73 Z M 254.85 152.95 L 251.97 150.08 L 255.26 146.81 L 251.97 143.54 L 254.85 140.68 L 258.14 143.95 L 261.43 140.7 L 264.31 143.54 L 261.02 146.83 L 264.31 150.08 L 261.41 152.95 L 258.14 149.69 Z M 256.37 195.19 L 250.46 189.33 L 253.4 186.39 L 256.41 189.42 L 262.95 182.93 L 265.83 185.79 Z" fill="#ffffff" stroke="none" pointer-events="all"/><rect x="280" y="151" width="90" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 166px; margin-left: 325px;"><div data-drawio-colors="color: #000000; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Configuration</div></div></div></foreignObject><text x="325" y="170" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Configuration</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/docs/score_tools/doc_as_code.rst b/docs/score_tools/doc_as_code.rst new file mode 100644 index 0000000000..331816240e --- /dev/null +++ b/docs/score_tools/doc_as_code.rst @@ -0,0 +1,181 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. document:: Doc-as-Code + :id: doc__tool__doc_as_code + :status: draft + :safety: ASIL_B + :security: YES + :tags: tool_management + + +Doc-as-Code Verification Report +=============================== + + +Identification +-------------- +| UID Doc-as-Code +| Version: release-0.2.4 +| Status: evaluated +| Tcl: low +| Safety_affected: yes +| Security_affected: yes + +(todo: discuss to update metamodel with the attributes above, what can be automated?) + + +Introduction +------------ + +Scope and purpose +~~~~~~~~~~~~~~~~~ +Generate documentation (.html files) based on text files (.rst / .md) and configuration data. + + +Inputs and outputs +~~~~~~~~~~~~~~~~~~ + +Inputs are restructured text files (.rst) and markdown files (,md) +Outputs are HTML files (.html) + +.. figure:: _assets/doc_as_code.drawio.svg + :width: 100% + :align: center + :alt: Doc-as-Code overview + + Doc-as-Code overview + +Available information +~~~~~~~~~~~~~~~~~~~~~ + +Project Documentation is available here: + +`Doc-as-Code Project Documentation <https://eclipse-score.github.io/docs-as-code/main/index.html>`_ + +This includes getting started or usage information and integration manual. + +The capabilities of the tool can be found here: + +`Doc-as-Code Project Capabilities <https://eclipse-score.github.io/docs-as-code/main/product/capabilities.html#capabilities>`_ + + +Installation and integration +---------------------------- + +Tool location: + +`Release 0.4.2 <https://github.com/eclipse-score/docs-as-code/tree/v0.4.2>`_ + +How to integrate: + +`Doc-as-Code Integration <https://eclipse-score.github.io/docs-as-code/main/how-to-integrate/index.html>`_ + +Environment: github, python, Version 3.y.z, sphinx, Version x.y.z, sphinx-needs, Version x.y.z +Supported platforms: Windows, Linux + + +Evaluation +---------- + +.. list-table:: S-CORE software modules overview + :header-rows: 1 + + * - Use case Identification + - Use case Description + - Malfunctions + - Impact on safety? + - Impact safety measures available? + - Impact safety detection sufficient? + - Threats + - Impact on security? + - Impact security measures available? + - Impact security detection sufficient? + - Further additional safety measure required? + - Confidence (automatic calculation) + * - 1 + - Generate element (requirements, architecture, safety analysis, ...) + - Wrong or missed element may lead to an wrong implementation with any potential error + - yes + - Reviews + - no + - Gain access to modify or run manipulated Doc-as-code or to to modify input files + - yes + - Access control, roles in Github + - yes + - Compare generated text in documentation with original text (#PR) + - low + * - 2 + - Link elements + - Wrong or missed links may lead to wrong elements and finally to wrong implementation with any potential error + - yes + - Reviews, Link rules checker + - no + - Gain access to modify or run manipulated Doc-as-code or to to modify input files + - yes + - Access control, roles in Github + - yes + - Compare generated links in documentation with original links (#PR) + - low + * - 3 + - Generate statistics + - Wrong or missing statistics may lead to wrong compliance statements, KPI reports, decisions + - yes + - Spot checks + - no + - Gain access to modify or run manipulated Doc-as-code or to to modify input files + - yes + - Access control, roles in Github + - yes + - Add diverse statistic generator tool (#PR) + - low + * - 4 + - Check documentation rules based on configuration + - Checks are not properly implemented, so may lead to wrong elements/links + - yes + - Code reviews, test for rules + - yes + - Gain access to modify or run manipulated Doc-as-code or to to modify input files + - yes + - Access control, roles in Github + - yes + - n/a + - high + + +Result +~~~~~~ +Tool Qualification Required + + +Tool Qualification +------------------ +Based on method: validation of the software tool + + +Requirements and testing aspects +-------------------------------- +Tool requirements are defined here: + +`Doc-as-Code Requirements <https://eclipse-score.github.io/docs-as-code/main/product/requirements.html#requirements>`_ + +Test cases and tests are defined here: + +`Doc-as-Code Test cases and tests <https://github.com/eclipse-score/docs-as-code/tree/v0.4.2/src/extensions>`_ + +The tests are part of the rules checker code sections. + +Requirements coverage is documented here: + +`Doc-as-Code Requirements <https://eclipse-score.github.io/docs-as-code/main/product/requirements.html#requirements>`_ diff --git a/docs/score_tools/index.rst b/docs/score_tools/index.rst new file mode 100644 index 0000000000..641f6e26e2 --- /dev/null +++ b/docs/score_tools/index.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # Copyright (c) 2024 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _tools: + +S-CORE Tools Overview +===================== + +.. needtable:: Tools List + :tags: tool_management + :filter: "tool_management" in tags and type == "document" and is_external == False + :style: table + :sort: status + :columns: id as "UID";title as "TITLE";status as "STATUS";safety as "SAFETY" + :colwidths: 30,30,30,30 + +.. toctree:: + :hidden: + :maxdepth: 2 + + doc_as_code From 810f385f2682f1044ce7bb88b900f793895ad258 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Tue, 15 Jul 2025 15:37:17 +0200 Subject: [PATCH 073/102] Tailor HSI document from safety part of PMP Ref: Resolves #1304 --- docs/contribute/general/folder.rst | 3 +-- .../safety_management.rst | 15 +++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/contribute/general/folder.rst b/docs/contribute/general/folder.rst index ebe3a30f24..8934271053 100644 --- a/docs/contribute/general/folder.rst +++ b/docs/contribute/general/folder.rst @@ -100,8 +100,7 @@ The modules and components shall follow the folder structure which was presented docs/ -> Documentation of the component architecture/ -> Component architecture (only if lower level components exist) [:need:`PROCESS_wp__component_arch`]. - requirements/ -> Component requirements [:need:`PROCESS_wp__requirements__comp`], - HSI (if relevant) [:need:`PROCESS_wp__hsi`] + requirements/ -> Component requirements [:need:`PROCESS_wp__requirements__comp`] safety_analysis/ -> Safety analysis on component level [:need:`PROCESS_wp__sw_component_safety_analysis`] verification/ -> Architecture review [:need:`PROCESS_wp__sw_arch_verification`], diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index c3c59bc537..89a77809ae 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -16,7 +16,7 @@ :id: doc__platform_safety_plan :status: draft :safety: ASIL_B - :realizes: PROCESS_wp__platform_safety_plan + :realizes: PROCESS_wp__platform_safety_plan,PROCESS_wp__tailoring :tags: platform_management Safety management / Platform Safety Plan @@ -117,15 +117,10 @@ Because in the S-CORE SW platform integration of safety-related systems not deve Because in the S-CORE SW platform no ASIL decomposition is planned: :need:`PROCESS_std_wp__iso26262__analysis_551`, :need:`PROCESS_std_wp__iso26262__analysis_552` -.. workproduct:: Tailoring Document Platform - :id: wp__tailoring_platform - :status: valid - :tags: safety_mgt - :complies: PROCESS_std_wp__iso26262__management_751, PROCESS_std_wp__iso26262__system_652, PROCESS_std_wp__iso26262__system_653, PROCESS_std_wp__iso26262__system_654, PROCESS_std_wp__iso26262__system_655, PROCESS_std_wp__iso26262__system_656, PROCESS_std_wp__iso26262__system_657, PROCESS_std_wp__iso26262__system_751, PROCESS_std_wp__iso26262__system_752, PROCESS_std_wp__iso26262__system_851, PROCESS_std_wp__iso26262__system_852, PROCESS_std_wp__iso26262__software_1151, PROCESS_std_wp__iso26262__software_1152, PROCESS_std_wp__iso26262__software_app_c_52, PROCESS_std_wp__iso26262__software_app_c_54, PROCESS_std_wp__iso26262__software_app_c_57, PROCESS_std_wp__iso26262__support_551, PROCESS_std_wp__iso26262__support_552, PROCESS_std_wp__iso26262__support_553, PROCESS_std_wp__iso26262__support_554, PROCESS_std_wp__iso26262__support_555, PROCESS_std_wp__iso26262__support_1351, PROCESS_std_wp__iso26262__support_1352, PROCESS_std_wp__iso26262__support_1353, PROCESS_std_wp__iso26262__support_1451, PROCESS_std_wp__iso26262__support_1452, PROCESS_std_wp__iso26262__support_1551, PROCESS_std_wp__iso26262__support_1651, PROCESS_std_wp__iso26262__analysis_551, PROCESS_std_wp__iso26262__analysis_552 - - This work product instantiation links to all the work products which are tailored out in the platform safety plan, - to be able to demonstrate completeness in `REPLACE external_standards`, and this is a document, not work product - +Because HSI is coming from HW (and systems) engineering which are not part of S-CORE +and the standard only asks for refinement during SW development. As the input is missing, there is nothing to refine. +Expectations towards the HW/Environment are covered by AoUs. Additionally S-CORE only provides reference HW integration, +so every user of the platform would have to redo the effort anyway: :need:`PROCESS_std_wp__iso26262__software_652` Approach From eeb35048d77cc23b0bdb67a0e56e3c265afcf263 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Mon, 14 Jul 2025 16:35:35 +0200 Subject: [PATCH 074/102] Correct Baselibs reqs ASIL - enable check --- MODULE.bazel | 2 +- docs/features/baselibs/docs/requirements/index.rst | 8 ++++---- docs/requirements/stakeholder/index.rst | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 56e4ad9214..62bad4b56e 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -90,5 +90,5 @@ bazel_dep(name = "score_cr_checker", version = "0.2.2") bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs -bazel_dep(name = "score_docs_as_code", version = "0.3.3") +bazel_dep(name = "score_docs_as_code", version = "0.4.2") bazel_dep(name = "score_process", version = "1.0.1") diff --git a/docs/features/baselibs/docs/requirements/index.rst b/docs/features/baselibs/docs/requirements/index.rst index f8b783bd12..2eb34704b0 100644 --- a/docs/features/baselibs/docs/requirements/index.rst +++ b/docs/features/baselibs/docs/requirements/index.rst @@ -30,17 +30,17 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__functional_req__base_libraries + :satisfies: stkh_req__functional_req__base_libraries, stkh_req__dependability__automotive_safety :status: valid - The base libraries shall implement functionality necessary to support safety-relevant platform components up to ASIL-B. + The base libraries shall implement functionality necessary to support safety-relevant platform components up to ASIL-B for selected functionalities. .. feat_req:: Multi-Language APIs :id: feat_req__baselibs__multi_language_apis :reqtype: Functional :security: NO - :safety: QM - :satisfies: stkh_req__functional_req__base_libraries, stkh_req__dev_experience__prog_languages + :safety: ASIL_B + :satisfies: stkh_req__functional_req__base_libraries, stkh_req__dev_experience__prog_languages, stkh_req__dependability__automotive_safety :status: valid The base libraries shall provide APIs for C++, Rust, or both, depending on the requirements of consuming platform components. diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 151ae8768b..4e64d00621 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -127,7 +127,7 @@ Functional requirements :id: stkh_req__functional_req__base_libraries :reqtype: Functional :security: YES - :safety: ASIL_B + :safety: QM :rationale: Common libraries reduce duplication, improve consistency and quality across components. :status: valid From 441a1df4017f4e900d77e4f9e8b0f78ccca3e200 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Tue, 15 Jul 2025 11:34:50 +0200 Subject: [PATCH 075/102] Correct Kvs reqs ASIL --- MODULE.bazel | 2 +- .../persistency/kvs/architecture/index.rst | 4 +- .../persistency/kvs/requirements/index.rst | 160 +++++++++++++----- 3 files changed, 116 insertions(+), 50 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 62bad4b56e..fd73b7d701 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -91,4 +91,4 @@ bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs bazel_dep(name = "score_docs_as_code", version = "0.4.2") -bazel_dep(name = "score_process", version = "1.0.1") +bazel_dep(name = "score_process", version = "1.0.2") diff --git a/docs/features/persistency/kvs/architecture/index.rst b/docs/features/persistency/kvs/architecture/index.rst index 21ee05d945..60862ea825 100644 --- a/docs/features/persistency/kvs/architecture/index.rst +++ b/docs/features/persistency/kvs/architecture/index.rst @@ -45,7 +45,7 @@ Static Architecture :security: YES :safety: ASIL_B :includes: logic_arc_int__persistency__interface - :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__stable_api,feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value + :fulfils: feat_req__persistency__default_value_get,feat_req__persistency__default_values,feat_req__persistency__events,feat_req__persistency__integrity_check,feat_req__persistency__persist_data,feat_req__persistency__persistency,feat_req__persistency__snapshots,feat_req__persistency__support_datatype_keys,feat_req__persistency__support_datatype_value :status: valid .. uml:: _assets/kvs_static_view.puml @@ -123,7 +123,7 @@ Logical Interfaces :id: logic_arc_int__persistency__interface :security: YES :safety: ASIL_B - :fulfils: feat_req__persistency__stable_api + :fulfils: feat_req__persistency__async_api :status: valid .. uml:: _assets/kvs_interface.puml diff --git a/docs/features/persistency/kvs/requirements/index.rst b/docs/features/persistency/kvs/requirements/index.rst index a9cf044a00..d93286eb33 100644 --- a/docs/features/persistency/kvs/requirements/index.rst +++ b/docs/features/persistency/kvs/requirements/index.rst @@ -12,9 +12,18 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* + +.. _feature_requirements_PersistencyKvs: + Requirements ############ +.. document:: Persistency KVS Feature Requirements + :id: doc__persistency_kvs_feat_reqs + :status: valid + :safety: ASIL_B + :realizes: wp__feature_reqs + .. feat_req:: C++ & Rust Interoperability :id: feat_req__persistency__cpp_rust_interop :reqtype: Non-Functional @@ -23,7 +32,8 @@ Requirements :satisfies: stkh_req__dev_experience__prog_languages :status: valid - The KVS system shall provide access through both C++ and Rust interfaces. + The Key-Value-Storage shall provide access through both C++ and Rust + interfaces. .. feat_req:: Maximum Size :id: feat_req__persistency__maximum_size @@ -31,9 +41,10 @@ Requirements :security: NO :safety: ASIL_B :satisfies: stkh_req__functiona_req__support_of_store - :status: invalid + :status: valid - The KVS system shall support specification of its maximum capacity at compile time. + The Key-Value-Storage shall support specification of its maximum size at + compile time. .. feat_req:: Multiple KVS per Software Architecture Element :id: feat_req__persistency__multiple_kvs @@ -43,7 +54,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall allow instantiating multiple independent stores per software architecture element. + The Key-Value-Storage shall allow instantiating multiple independent stores + per software architecture element. .. feat_req:: Supported Datatypes (Keys) :id: feat_req__persistency__support_datatype_keys @@ -53,7 +65,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support UTF-8 encoded strings as valid key types. + The Key-Value-Storage shall support UTF-8 encoded strings as valid key + types. .. feat_req:: Supported Datatypes (Values) :id: feat_req__persistency__support_datatype_value @@ -62,9 +75,11 @@ Requirements :safety: ASIL_B :satisfies: stkh_req__functiona_req__support_of_store :status: valid + :tags: persistency - The KVS system shall support storing both primitive and non-primitive datatypes as values. - The supported datatypes shall match those used by the IPC feature. + The Key-Value-Storage shall support storing both primitive and non-primitive + datatypes as values. The supported datatypes shall match those used by the + IPC feature. .. feat_req:: Default Values :id: feat_req__persistency__default_values @@ -74,7 +89,7 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support predefined default values for keys. + The Key-Value-Storage shall support predefined default values for keys. .. feat_req:: Default Value Retrieval :id: feat_req__persistency__default_value_get @@ -84,7 +99,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support retrieving the default value associated with a key. + The Key-Value-Storage shall support retrieving the default value associated + with a key. .. feat_req:: Default Value Reset :id: feat_req__persistency__default_value_reset @@ -94,7 +110,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support resetting a single key or all keys to their respective default values. + The Key-Value-Storage shall support resetting a single key or all keys to + their respective default values. .. feat_req:: Persistency :id: feat_req__persistency__persistency @@ -104,7 +121,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall persist stored data and provide an API to explicitly trigger persistence. + The Key-Value-Storage shall persist stored data and provide an API to + explicitly trigger persistence. .. feat_req:: Integrity Check :id: feat_req__persistency__integrity_check @@ -114,7 +132,7 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall detect and report data corruption. + The Key-Value-Storage shall detect and report data corruption. Note: Implementation depends on AoUs. .. feat_req:: Versioning @@ -125,7 +143,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support versioning for different layout configurations. + The Key-Value-Storage shall support versioning for different layout + configurations. .. feat_req:: Update Mechanism :id: feat_req__persistency__update_mechanism @@ -135,7 +154,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall implement mechanisms to upgrade from one version to another, including multi-version jumps. + The Key-Value-Storage shall implement mechanisms to upgrade from one version + to another, including multi-version jumps. .. feat_req:: Snapshots :id: feat_req__persistency__snapshots @@ -145,8 +165,9 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall support explicit creation of snapshots identified by unique IDs and allow rollback to previous snapshots. - Snapshots shall also be deletable. + The Key-Value-Storage shall support explicit creation of snapshots + identified by unique IDs and allow rollback to previous snapshots. Snapshots + shall also be deletable. .. feat_req:: Tooling :id: feat_req__persistency__tooling @@ -156,17 +177,8 @@ Requirements :satisfies: stkh_req__functiona_req__support_of_store :status: valid - The KVS system shall provide tooling support for viewing and modifying key-value pairs during development and debugging. - -.. feat_req:: Stable APIs - :id: feat_req__persistency__stable_api - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__communication__stable_app_inter - :status: valid - - The KVS API shall remain stable throughout its lifecycle while enabling the addition of new functionalities. + The Key-Value-Storage shall provide tooling support for viewing and + modifying key-value pairs during development and debugging. .. feat_req:: Variant management support :id: feat_req__persistency__variant_management @@ -176,68 +188,85 @@ Requirements :satisfies: stkh_req__overall_goals__variant_management :status: valid - The KVS shall ensure compatibility across different architectures and versions. + The Key-Value-Storage shall ensure compatibility across different + architectures and versions. .. feat_req:: Set default key values via file :id: feat_req__persistency__default_value_file :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__functional_req__file_based :status: valid - The KVS shall support the configuration of default key values using an external file. + The Key-Value-Storage shall support the configuration of default key values + using an external file. .. feat_req:: Configure limits via file :id: feat_req__persistency__config_file :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__functional_req__file_based :status: valid - The KVS shall support the configuration of memory and other resource limits via a configuration file. + The Key-Value-Storage shall support the configuration of memory and other + resource limits via a configuration file. .. feat_req:: Store persistent data :id: feat_req__persistency__persist_data :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__functional_req__data_persistency :status: valid - The KVS shall support storing and loading its data to and from persistent storage. + The Key-Value-Storage shall support storing and loading its data to and from + persistent storage. -.. feat_req:: Support engineering and field mode - :id: feat_req__persistency__dev_mode +.. feat_req:: Support engineering mode + :id: feat_req__persistency__eng_mode :reqtype: Functional :security: NO :safety: ASIL_B :satisfies: stkh_req__dependability__safety_features :status: valid - The KVS shall provide both engineering (developer) and field modes. + The Key-Value-Storage shall an engineering (developer) mode. The engineering mode shall allow unrestricted data access. +.. feat_req:: Support field mode + :id: feat_req__persistency__field_mode + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features + :status: valid + + The Key-Value-Storage shall a field mode. + The field mode should enforce the most restrictive data access controls feasible. + .. feat_req:: Provide an async API :id: feat_req__persistency__async_api :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__dependability__availability, stkh_req__app_architectures__support_request :status: valid - The KVS shall provide an asynchronous API for accessing and manipulating data. + The Key-Value-Storage shall provide an asynchronous API for accessing and + manipulating data. .. feat_req:: Separate data stores :id: feat_req__persistency__access_control :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__dependability__security_features :status: valid - The KVS shall ensure that only authorized components can access individual data stores. + The Key-Value-Storage shall ensure that only authorized components can + access individual data stores. .. feat_req:: Data-change events :id: feat_req__persistency__events @@ -247,9 +276,9 @@ Requirements :satisfies: stkh_req__app_architectures__support_data :status: valid - The KVS shall provide an API that allows for the registration of callback - functions. These callbacks shall be invoked in response to specific events, - such as when keys are changed or removed. + The Key-Value-Storage shall provide an API that allows for the registration + of callback functions. These callbacks shall be invoked in response to + specific events, such as when keys are changed or removed. .. feat_req:: Fast access :id: feat_req__persistency__fast_access @@ -259,14 +288,51 @@ Requirements :satisfies: stkh_req__execution_model__short_app_cycles :status: valid - The KVS shall ensure that key operations are typically completed within 5 milliseconds. + The Key-Value-Storage shall ensure that key operations are completed within + 5 milliseconds. .. feat_req:: Intra-Process Data Access :id: feat_req__persistency__intra_process_comm :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__communication__intra_process :status: valid - The KVS shall support concurrent intra-process data access. + The Key-Value-Storage shall support concurrent intra-process data access. + +.. needextend:: docname is not None + :+tags: persistency + +AoU Requirements +################ + +.. aou_req:: Persistency Error handling + :id: aou_req__persistency__error_handling + :reqtype: Functional + :security: NO + :safety: ASIL_B + :status: valid + :tags: environment + + The application shall handle if the feature persistency is not available. + +.. aou_req:: Application deadlock + :id: aou_req__persistency__appl_design + :reqtype: Functional + :security: NO + :safety: ASIL_B + :status: valid + :tags: environment + + The application shall be designed in a way that deadlocks are avoided. + +.. aou_req:: Application execution + :id: aou_req__persistency__appl_exec + :reqtype: Functional + :security: NO + :safety: ASIL_B + :status: valid + :tags: environment + + The execution of persistency shall not be blocked by the application. From e174ba6064419e84e7d6abfba2d8f245344b3f11 Mon Sep 17 00:00:00 2001 From: Jochen Hoenle <jochen.hoenle@bmw.de> Date: Tue, 15 Jul 2025 15:19:58 +0200 Subject: [PATCH 076/102] lola: adapt ASIL Level for checks --- .../communication/docs/requirements/index.rst | 54 +++++++++---------- docs/requirements/stakeholder/index.rst | 6 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/features/communication/docs/requirements/index.rst b/docs/features/communication/docs/requirements/index.rst index bd54688a6e..eaed4cf5ba 100644 --- a/docs/features/communication/docs/requirements/index.rst +++ b/docs/features/communication/docs/requirements/index.rst @@ -22,7 +22,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time, stkh_req__communication__safe :status: valid The communication framework shall provide API to support a time-based architecture. @@ -52,7 +52,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data,stkh_req__app_architectures__support_request + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data,stkh_req__app_architectures__support_time, stkh_req__communication__safe, stkh_req__app_architectures__support_request :status: valid A communication interface consists of a combination of any number of the following elements: @@ -66,7 +66,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_data + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time :status: valid An event-type is part of a communication interface and has: @@ -82,7 +82,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_request + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_request, stkh_req__communication__safe :status: valid A method is part of a communication interface and has: @@ -102,7 +102,7 @@ Requirements :reqtype: Functional :security: NO :safety: QM - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_request :status: valid A signal is part of a communication interface and has: @@ -124,7 +124,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time + :satisfies: stkh_req__communication__inter_process, stkh_req__app_architectures__support_time, stkh_req__communication__safe :status: valid Communication shall be cached based on the producer-consumer pattern. @@ -134,7 +134,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Multiple service instances shall be able to offer the same interface. @@ -147,7 +147,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid A service instance is offered under one or more unique names by which it can be discovered. @@ -162,7 +162,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The communication framework shall support versioning of service instances: @@ -178,7 +178,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The interface to access service instances is agnostic to the binding used to communicate with the service. @@ -191,7 +191,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The communication framework shall support stateless communication. @@ -205,7 +205,7 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The communication framework shall support multiple service instances per software architecture element. @@ -218,10 +218,10 @@ Requirements :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid - The communication framework shall provide service discovery to find available services during runtime. Service discovery shall consider version compatibility. Service discovery shall be handled implicitly (where possible). + The communication framework shall provide service discovery to find available services during runtime. Service discovery shall consider version compatibility. Service discovery shall be handled implicitly (where possible). .. note:: The service discovery may be restricted/impacted by availability of deployment information. @@ -235,7 +235,7 @@ Mixed-Criticality safety systems :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The communication framework shall support safe communication involving communication partners on the same or multiple @@ -246,7 +246,7 @@ Mixed-Criticality safety systems :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Consumers with lower criticality shall not be able to corrupt data consumed by partners with higher criticality. @@ -256,7 +256,7 @@ Mixed-Criticality safety systems :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Consumers with lower criticality shall not be able to modify the order of data consumed by partners with higher @@ -267,7 +267,7 @@ Mixed-Criticality safety systems :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Consumers with lower criticality shall not be able to duplicate data consumed by other communication partners with @@ -278,7 +278,7 @@ Mixed-Criticality safety systems :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Consumers with lower criticality shall not be able to drop data before it is consumed by partners with higher @@ -293,7 +293,7 @@ Performance :reqtype: Functional :security: NO :safety: QM - :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data + :satisfies: stkh_req__communication__inter_process,stkh_req__app_architectures__support_data, stkh_req__app_architectures__support_request :status: valid The communication framework shall enable Zero-Copy communication without copying to-be-transferred data. @@ -409,7 +409,7 @@ Dynamic deployment at runtime :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid Deployment configuration shall be read from an integrity-checked configuration file at runtime. @@ -422,7 +422,7 @@ Tracing :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__dev_experience__tracing_of_comm + :satisfies: stkh_req__dev_experience__tracing_of_comm, stkh_req__communication__safe :status: valid The communication framework shall provide infrastructure to enable binding-agnostic, zero-copy, read-only tracing of @@ -436,7 +436,7 @@ Security Impact :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__dependability__security_features :status: valid The communication framework shall support an Access Control Lists in the deployment configuration. @@ -446,7 +446,7 @@ Security Impact :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__dependability__security_features :status: valid The communication framework shall support an Access Control List per service instance. @@ -456,7 +456,7 @@ Security Impact :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__dependability__security_features :status: valid The communication framework shall support an Access Control List for the communication partner offering a service @@ -468,7 +468,7 @@ Security Impact :reqtype: Functional :security: YES :safety: QM - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__dependability__security_features :status: valid The communication framework shall support an Access Control List for the communication partner consuming a service @@ -483,7 +483,7 @@ Safety Impact :reqtype: Functional :security: YES :safety: ASIL_B - :satisfies: stkh_req__communication__inter_process + :satisfies: stkh_req__communication__inter_process, stkh_req__communication__safe :status: valid The communication framework shall support safe communication up to ASIL-B. diff --git a/docs/requirements/stakeholder/index.rst b/docs/requirements/stakeholder/index.rst index 4e64d00621..de63a11d64 100644 --- a/docs/requirements/stakeholder/index.rst +++ b/docs/requirements/stakeholder/index.rst @@ -351,7 +351,7 @@ interaction)** — each emphasize different operational priorities. :id: stkh_req__app_architectures__support_data :reqtype: Functional :security: NO - :safety: ASIL_B + :safety: QM :rationale: tbd - potentially above explanation :status: valid @@ -361,7 +361,7 @@ interaction)** — each emphasize different operational priorities. :id: stkh_req__app_architectures__support_request :reqtype: Functional :security: NO - :safety: ASIL_B + :safety: QM :rationale: tbd - potentially above explanation :status: valid @@ -445,7 +445,7 @@ Communication :id: stkh_req__communication__inter_process :reqtype: Functional :security: NO - :safety: ASIL_B + :safety: QM :rationale: Application software typically consists of multiple processes which need to interact. :status: valid From 2fc0dc42b246788c5f1e00687ee1587cb8d532ae Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Wed, 16 Jul 2025 15:09:14 +0200 Subject: [PATCH 077/102] Update doc-as-code version - better checks --- MODULE.bazel | 4 ++-- docs/features/persistency/kvs/requirements/index.rst | 2 +- docs/platform_management_plan/change_management.rst | 4 ++-- docs/platform_management_plan/config_management.rst | 2 +- docs/platform_management_plan/documentation_management.rst | 2 +- docs/platform_management_plan/problem_resolution.rst | 5 ++--- docs/platform_management_plan/project_management.rst | 2 +- docs/platform_management_plan/quality_management.rst | 7 ------- docs/platform_management_plan/safety_management.rst | 2 +- docs/platform_management_plan/software_verification.rst | 6 +++--- docs/score_releases/platform_release_note.rst | 2 +- 11 files changed, 15 insertions(+), 23 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index fd73b7d701..6db0f02dc7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -90,5 +90,5 @@ bazel_dep(name = "score_cr_checker", version = "0.2.2") bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs -bazel_dep(name = "score_docs_as_code", version = "0.4.2") -bazel_dep(name = "score_process", version = "1.0.2") +bazel_dep(name = "score_docs_as_code", version = "0.4.3") +bazel_dep(name = "score_process", version = "1.0.4") diff --git a/docs/features/persistency/kvs/requirements/index.rst b/docs/features/persistency/kvs/requirements/index.rst index d93286eb33..75e90c8d21 100644 --- a/docs/features/persistency/kvs/requirements/index.rst +++ b/docs/features/persistency/kvs/requirements/index.rst @@ -22,7 +22,7 @@ Requirements :id: doc__persistency_kvs_feat_reqs :status: valid :safety: ASIL_B - :realizes: wp__feature_reqs + :realizes: PROCESS_wp__requirements__feat .. feat_req:: C++ & Rust Interoperability :id: feat_req__persistency__cpp_rust_interop diff --git a/docs/platform_management_plan/change_management.rst b/docs/platform_management_plan/change_management.rst index 15a508582c..b41a197653 100644 --- a/docs/platform_management_plan/change_management.rst +++ b/docs/platform_management_plan/change_management.rst @@ -17,7 +17,7 @@ :status: draft :safety: ASIL_B :tags: platform_management - :realizes: wp__chm_plan + :realizes: PROCESS_wp__chm_plan .. _change_mgmt_plan: @@ -110,7 +110,7 @@ Changes are clustered in the following types: Change Request Traceability Impact Analysis requires the following tools: -:need:`[[title]] <PROCESS_gd_req__change_tool_impact_analysis>` +:need:`[[title]] <PROCESS_gd_req__change__tool_impact_analysis>` Change Request Attributes ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/platform_management_plan/config_management.rst b/docs/platform_management_plan/config_management.rst index 9a8eaaa94f..60f8351966 100644 --- a/docs/platform_management_plan/config_management.rst +++ b/docs/platform_management_plan/config_management.rst @@ -136,7 +136,7 @@ Backup and Recovery ^^^^^^^^^^^^^^^^^^^ Backup and recovery are covered by the Eclipse Foundation hosting the GitHub service for S-CORE. -For the long term storage, additional measures are taken, see :need:`PROCESS_gd_req__workproducts_storage` +For the long term storage, additional measures are taken, see :need:`PROCESS_gd_req__config__workproducts_storage` Status and Reporting diff --git a/docs/platform_management_plan/documentation_management.rst b/docs/platform_management_plan/documentation_management.rst index f529b5260d..ebe6d0073f 100644 --- a/docs/platform_management_plan/documentation_management.rst +++ b/docs/platform_management_plan/documentation_management.rst @@ -17,7 +17,7 @@ :status: draft :safety: ASIL_B :tags: platform_management - :realizes: wp__document_mgt_plan + :realizes: PROCESS_wp__document_mgt_plan Documentation Management Plan ----------------------------- diff --git a/docs/platform_management_plan/problem_resolution.rst b/docs/platform_management_plan/problem_resolution.rst index a9e2083c76..9c4c4c553b 100644 --- a/docs/platform_management_plan/problem_resolution.rst +++ b/docs/platform_management_plan/problem_resolution.rst @@ -160,11 +160,10 @@ ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For :need:`[[title]] <PROCESS_gd_req__problem__attr_safety_affected>`, -:need:`[[title]] <PROCESS_gd_req__problem__attr_security_affected>`, -:need:`[[title]] <PROCESS_gd_req__problem__attr_quality_affected>` are defined in the description part of the +:need:`[[title]] <PROCESS_gd_req__problem__attr_security_affected>` are defined in the description part of the ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For S-CORE labels are defined to mark affected ISSUEs: -``safety``, ``security``, ``quality`` +``safety``, ``security`` Combinations of them are allowed. diff --git a/docs/platform_management_plan/project_management.rst b/docs/platform_management_plan/project_management.rst index e351faff7f..67d98b5bc6 100644 --- a/docs/platform_management_plan/project_management.rst +++ b/docs/platform_management_plan/project_management.rst @@ -16,7 +16,7 @@ :id: doc__project_mgt_plan :status: draft :safety: ASIL_B - :realizes: wp__project_mgt + :realizes: PROCESS_wp__project_mgt :tags: platform_management Project management plan diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index fc2728a648..aa68ca430e 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -379,13 +379,6 @@ None - <Link to WP> - <automated> - * - :need:`PROCESS_wp__hsi` - - n/a - - draft - - <Link to issue> - - <Link to WP> - - <automated> - * - :need:`PROCESS_wp__module_safety_manual` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index 89a77809ae..e24105e08c 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -248,7 +248,7 @@ Functional Safety Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Requirement Engineering is defined in the process description. See :need:`doc__project_mgt_plan`. -The application of ISO 26262 standards requirements is realized by defining process guidances and matching those to the ISO 26262 requirements (see e.g. for example :need:`PROCESS_gd_req__sm_doc_status`). +The application of ISO 26262 standards requirements is realized by defining process guidances and matching those to the ISO 26262 requirements (see e.g. for example :need:`PROCESS_gd_req__safety__doc_status`). Functional Safety Schedule ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/platform_management_plan/software_verification.rst b/docs/platform_management_plan/software_verification.rst index ebed31fe77..e0ade6494a 100644 --- a/docs/platform_management_plan/software_verification.rst +++ b/docs/platform_management_plan/software_verification.rst @@ -342,7 +342,7 @@ Test development The verification steps as well as the development of test cases is done along with the implementation of code. A full automation of tests should be achieved and the derived test cases should contain meta -data that gives further information as defined in :need:`PROCESS_gd_req__link_tests`. The list of +data that gives further information as defined in :need:`PROCESS_gd_req__verification__link_tests`. The list of relevant work products is shown above (as part of the development of the product). The different environments that can be used for the test development are defined below. @@ -352,7 +352,7 @@ Pre-existing test cases The recommendations according to the :need:`PROCESS_gd_guidl__verification_guide` for pre-existing test cases is followed. Any pre-existing test case (e.g. from OSS components) is reviewed and adopted -to follow the :need:`PROCESS_gd_guidl__verification_specification` and :need:`PROCESS_gd_req__link_tests`. +to follow the :need:`PROCESS_gd_guidl__verification_specification` and :need:`PROCESS_gd_req__verification__link_tests`. Test execution and result analysis ---------------------------------- @@ -418,7 +418,7 @@ The following test level fall in the responsibility of the :need:`PROCESS_rl__co Unit tests can be the developed by the same :need:`PROCESS_rl__contributor` who also contributed the unit code. A level of independence is achieved as the review process demands to have a review by a :need:`PROCESS_rl__committer` -different to the author of a Pull Request. This is also described in process requirement :need:`PROCESS_gd_req__verification_independence`. +different to the author of a Pull Request. This is also described in process requirement :need:`PROCESS_gd_req__verification__independence`. Note that, each :need:`PROCESS_rl__contributor` of the project acts in a publicly visible space where also others see the contribution and have the possibility to perform additional reviews independent from diff --git a/docs/score_releases/platform_release_note.rst b/docs/score_releases/platform_release_note.rst index ceb61558a0..37a24eb18b 100644 --- a/docs/score_releases/platform_release_note.rst +++ b/docs/score_releases/platform_release_note.rst @@ -21,7 +21,7 @@ Platform Release Notes :id: doc__platform_release_note :status: draft :safety: ASIL_B - :realizes: wp__platform_sw_release_note + :realizes: PROCESS_wp__platform_sw_release_note | Platform Name: [S-CORE] | Release Tag: v0.5.0 From b9814547635a514d65f5ef9ff313f8b1b10c9aea Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Wed, 16 Jul 2025 11:33:01 +0200 Subject: [PATCH 078/102] Tailoring in of Safety Mechanisms Ref: Resolves #1431 --- .../safety_management.rst | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index 89a77809ae..9327f0e6e0 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -82,46 +82,50 @@ Tailoring of safety activities: The following ISO 26262 defined safety work products are not relevant for the S-CORE SW platform development: -Because these are in responsibility of the system integrator: :need:`PROCESS_std_wp__iso26262__management_751`, -:need:`PROCESS_std_wp__iso26262__system_652`, :need:`PROCESS_std_wp__iso26262__system_653`, :need:`PROCESS_std_wp__iso26262__system_654`, -:need:`PROCESS_std_wp__iso26262__system_655`, :need:`PROCESS_std_wp__iso26262__system_656`, :need:`PROCESS_std_wp__iso26262__system_657`, -:need:`PROCESS_std_wp__iso26262__system_751`, :need:`PROCESS_std_wp__iso26262__system_752`, :need:`PROCESS_std_wp__iso26262__system_851`, -:need:`PROCESS_std_wp__iso26262__system_852` +* Because these are in responsibility of the system integrator: :need:`PROCESS_std_wp__iso26262__management_751`, + :need:`PROCESS_std_wp__iso26262__system_652`, :need:`PROCESS_std_wp__iso26262__system_653`, :need:`PROCESS_std_wp__iso26262__system_654`, + :need:`PROCESS_std_wp__iso26262__system_655`, :need:`PROCESS_std_wp__iso26262__system_656`, :need:`PROCESS_std_wp__iso26262__system_657`, + :need:`PROCESS_std_wp__iso26262__system_751`, :need:`PROCESS_std_wp__iso26262__system_752`, :need:`PROCESS_std_wp__iso26262__system_851`, + :need:`PROCESS_std_wp__iso26262__system_852` -Note that stakeholder requirements (:need:`PROCESS_std_wp__iso26262__system_651`) are in scope of the project, -to be able to cover System and HW related failures which are usually covered by SW (e.g. end to end protection for ECU external communication). -But those are the "Assumed Technical Safety Requirements" of the SW platform SEooC and do not need to be tested by SEooC supplier. -I.e. the system testing is out of scope. Note that S-CORE will implement platform test of stakeholder requirements for demonstration, -but these are not intended to be completely covering the stakeholder requirements. -There will be SW integration tests of feature requirements, as required by ISO 26262 part 6-10. -These may be reused by the users on their HW platform to cover Technical Safety Requirements towards the SW platform. -But if these are sufficiently also covering the TSRs must be analyzed and decided by the user. + Note that stakeholder requirements (:need:`PROCESS_std_wp__iso26262__system_651`) are in scope of the project, + to be able to cover System and HW related failures which are usually covered by SW (e.g. end to end protection for ECU external communication). + But those are the "Assumed Technical Safety Requirements" of the SW platform SEooC and do not need to be tested by SEooC supplier. + I.e. the system testing is out of scope. Note that S-CORE will implement platform test of stakeholder requirements for demonstration, + but these are not intended to be completely covering the stakeholder requirements. + There will be SW integration tests of feature requirements, as required by ISO 26262 part 6-10. + These may be reused by the users on their HW platform to cover Technical Safety Requirements towards the SW platform. + But if these are sufficiently also covering the TSRs must be analyzed and decided by the user. -Also tailored out is the SW testing on the target, as the S-CORE project can only test on reference HW -(part of SW integration testing). So these are not relevant: :need:`PROCESS_std_wp__iso26262__software_1151`, :need:`PROCESS_std_wp__iso26262__software_1152` +* Also tailored out is the SW testing on the target, as the S-CORE project can only test on reference HW + (part of SW integration testing). So these are not relevant: :need:`PROCESS_std_wp__iso26262__software_1151`, :need:`PROCESS_std_wp__iso26262__software_1152` -Because there is no calibration used for the S-CORE SW platform components, only configuration: :need:`PROCESS_std_wp__iso26262__software_app_c_52`, -:need:`PROCESS_std_wp__iso26262__software_app_c_54`, :need:`PROCESS_std_wp__iso26262__software_app_c_57` +* Because there is no calibration used for the S-CORE SW platform components, only configuration: :need:`PROCESS_std_wp__iso26262__software_app_c_52`, + :need:`PROCESS_std_wp__iso26262__software_app_c_54`, :need:`PROCESS_std_wp__iso26262__software_app_c_57` -Because distributed development is not how the project is organized. All contributors are seen as part of the project team. -When used, OSS components are qualified and external SEooCs are integrated in the project scope: :need:`PROCESS_std_wp__iso26262__support_551`, -:need:`PROCESS_std_wp__iso26262__support_552`, :need:`PROCESS_std_wp__iso26262__support_553`, :need:`PROCESS_std_wp__iso26262__support_554`, :need:`PROCESS_std_wp__iso26262__support_555` +* Because distributed development is not how the project is organized. All contributors are seen as part of the project team. + When used, OSS components are qualified and external SEooCs are integrated in the project scope: :need:`PROCESS_std_wp__iso26262__support_551`, + :need:`PROCESS_std_wp__iso26262__support_552`, :need:`PROCESS_std_wp__iso26262__support_553`, :need:`PROCESS_std_wp__iso26262__support_554`, :need:`PROCESS_std_wp__iso26262__support_555` -Because in the S-CORE SW platform HW elements are out of scope: :need:`PROCESS_std_wp__iso26262__support_1351`, :need:`PROCESS_std_wp__iso26262__support_1352`, :need:`PROCESS_std_wp__iso26262__support_1353` +* Because in the S-CORE SW platform HW elements are out of scope: :need:`PROCESS_std_wp__iso26262__support_1351`, :need:`PROCESS_std_wp__iso26262__support_1352`, :need:`PROCESS_std_wp__iso26262__support_1353` -Because in the S-CORE SW platform a proven in use argument will not be applied: :need:`PROCESS_std_wp__iso26262__support_1451`, :need:`PROCESS_std_wp__iso26262__support_1452` +* Because in the S-CORE SW platform a proven in use argument will not be applied: :need:`PROCESS_std_wp__iso26262__support_1451`, :need:`PROCESS_std_wp__iso26262__support_1452` -Because in the S-CORE SW platform interfacing of out of scope of ISO 26262 applications is not planned: :need:`PROCESS_std_wp__iso26262__support_1551` +* Because in the S-CORE SW platform interfacing of out of scope of ISO 26262 applications is not planned: :need:`PROCESS_std_wp__iso26262__support_1551` -Because in the S-CORE SW platform integration of safety-related systems not developed according to ISO 26262 is not planned: :need:`PROCESS_std_wp__iso26262__support_1651` +* Because in the S-CORE SW platform integration of safety-related systems not developed according to ISO 26262 is not planned: :need:`PROCESS_std_wp__iso26262__support_1651` -Because in the S-CORE SW platform no ASIL decomposition is planned: :need:`PROCESS_std_wp__iso26262__analysis_551`, :need:`PROCESS_std_wp__iso26262__analysis_552` +* Because in the S-CORE SW platform no ASIL decomposition is planned: :need:`PROCESS_std_wp__iso26262__analysis_551`, :need:`PROCESS_std_wp__iso26262__analysis_552` -Because HSI is coming from HW (and systems) engineering which are not part of S-CORE -and the standard only asks for refinement during SW development. As the input is missing, there is nothing to refine. -Expectations towards the HW/Environment are covered by AoUs. Additionally S-CORE only provides reference HW integration, -so every user of the platform would have to redo the effort anyway: :need:`PROCESS_std_wp__iso26262__software_652` +* Because HSI is coming from HW (and systems) engineering which are not part of S-CORE + and the standard only asks for refinement during SW development. As the input is missing, there is nothing to refine. + Expectations towards the HW/Environment are covered by AoUs. Additionally S-CORE only provides reference HW integration, + so every user of the platform would have to redo the effort anyway: :need:`PROCESS_std_wp__iso26262__software_652` +But also some activities based on requirements defining what has to be done to create a workproduct which is in scope of the S-CORE platform are tailored: + +* Because those are not relevant for ASIL_B: :need:`PROCESS_std_req__iso26262__system_6423`, + :need:`PROCESS_std_req__iso26262__system_6424`, :need:`PROCESS_std_req__iso26262__system_6425` Approach ++++++++ From fb84e28716b78858a8dfe1127e4e2a4fa3005275 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Wed, 16 Jul 2025 16:45:50 +0200 Subject: [PATCH 079/102] Update FEO requirements ASIL --- .../requirements/component_requirements.rst | 30 +++++++++---------- .../frameworks/feo/requirements/index.rst | 20 ++++++------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst index 42568e7ac8..72e151e0fd 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst @@ -19,7 +19,7 @@ Component Requirements: feo :id: comp_req__feo__application :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__application :status: valid @@ -36,7 +36,7 @@ Component Requirements: feo :id: comp_req__feo__activity :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity :status: valid @@ -52,7 +52,7 @@ Component Requirements: feo :id: comp_req__feo__task_chain :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__task_chain :status: valid @@ -72,7 +72,7 @@ Component Requirements: feo :id: comp_req__feo__scheduler :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__application, feat_req__feo__agent :status: valid @@ -83,7 +83,7 @@ Component Requirements: feo :id: comp_req__feo__service_activity :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__service_activity :status: valid @@ -98,7 +98,7 @@ Component Requirements: feo :id: comp_req__feo__agent :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__agent :status: valid @@ -115,7 +115,7 @@ Component Requirements: feo :id: comp_req__feo__activitiy_thread :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity_init, feat_req__feo__activitiy_step, feat_req__feo__activity_shutdown, feat_req__feo__activity :status: valid @@ -127,7 +127,7 @@ Component Requirements: feo :id: comp_req__feo__application_lifecycle :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__application_lifecycle :status: valid @@ -138,7 +138,7 @@ Component Requirements: feo :id: comp_req__feo__activity_init :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity_init :status: valid @@ -152,7 +152,7 @@ Component Requirements: feo :id: comp_req__feo__activitiy_step :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activitiy_step, feat_req__feo__activity_init, feat_req__feo__activity :status: valid @@ -165,7 +165,7 @@ Component Requirements: feo :id: comp_req__feo__activity_shutdown :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity_shutdown :status: valid @@ -179,7 +179,7 @@ Component Requirements: feo :id: comp_req__feo__comp_cfg :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity, feat_req__feo__task_chain :status: valid @@ -194,7 +194,7 @@ Component Requirements: feo :id: comp_req__feo__comp_cfg_file :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity :status: valid @@ -205,7 +205,7 @@ Component Requirements: feo :id: comp_req__feo__act_map_cfg :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__activity :status: valid @@ -255,7 +255,7 @@ Component Requirements: feo :id: comp_req__feo__trustable_computation :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: feat_req__feo__trustable_computation :status: valid diff --git a/docs/features/frameworks/feo/requirements/index.rst b/docs/features/frameworks/feo/requirements/index.rst index c70140c76c..98d8e4ebcc 100644 --- a/docs/features/frameworks/feo/requirements/index.rst +++ b/docs/features/frameworks/feo/requirements/index.rst @@ -23,7 +23,7 @@ Definitions :id: feat_req__feo__application :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -40,7 +40,7 @@ Definitions :id: feat_req__feo__activity :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -57,7 +57,7 @@ Definitions :id: feat_req__feo__task_chain :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -76,7 +76,7 @@ Definitions :id: feat_req__feo__service_activity :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -89,7 +89,7 @@ Definitions :id: feat_req__feo__agent :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -112,7 +112,7 @@ Dynamic Architecture :id: feat_req__feo__application_lifecycle :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -122,7 +122,7 @@ Dynamic Architecture :id: feat_req__feo__activity_init :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -137,7 +137,7 @@ Dynamic Architecture :id: feat_req__feo__activitiy_step :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -149,7 +149,7 @@ Dynamic Architecture :id: feat_req__feo__activity_shutdown :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid @@ -202,7 +202,7 @@ Supervision :id: feat_req__feo__trustable_computation :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__dependability__safety_features, stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data :status: valid From 00c6cd6c9e576c6f5451633fb34f530e7b267326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Fri, 18 Jul 2025 11:10:25 +0200 Subject: [PATCH 080/102] Added Module Release Guide (#1445) --- .../general/_assets/Create_tag_on_publish.png | Bin 0 -> 22823 bytes .../_assets/Generate_release_notes_button.png | Bin 0 -> 28854 bytes .../_assets/Generated_release_notes.png | Bin 0 -> 55970 bytes .../general/_assets/Github_release_button.png | Bin 0 -> 243699 bytes .../_assets/Overview_before_release.png | Bin 0 -> 84138 bytes .../general/_assets/Release_select_tag.png | Bin 0 -> 79298 bytes .../general/_assets/Releases_other_way.png | Bin 0 -> 8575 bytes .../_assets/Releases_other_way_button.png | Bin 0 -> 47913 bytes docs/contribute/general/index.rst | 1 + docs/contribute/general/release_guide.rst | 292 ++++++++++++++++++ 10 files changed, 293 insertions(+) create mode 100644 docs/contribute/general/_assets/Create_tag_on_publish.png create mode 100644 docs/contribute/general/_assets/Generate_release_notes_button.png create mode 100644 docs/contribute/general/_assets/Generated_release_notes.png create mode 100644 docs/contribute/general/_assets/Github_release_button.png create mode 100644 docs/contribute/general/_assets/Overview_before_release.png create mode 100644 docs/contribute/general/_assets/Release_select_tag.png create mode 100644 docs/contribute/general/_assets/Releases_other_way.png create mode 100644 docs/contribute/general/_assets/Releases_other_way_button.png create mode 100644 docs/contribute/general/release_guide.rst diff --git a/docs/contribute/general/_assets/Create_tag_on_publish.png b/docs/contribute/general/_assets/Create_tag_on_publish.png new file mode 100644 index 0000000000000000000000000000000000000000..60708850aeff6d16570ef7360ba7a3da0d0ec390 GIT binary patch literal 22823 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�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 literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Generate_release_notes_button.png b/docs/contribute/general/_assets/Generate_release_notes_button.png new file mode 100644 index 0000000000000000000000000000000000000000..6e37f3268cb2c10437889e031d116c2768c16e00 GIT binary patch literal 28854 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 literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Generated_release_notes.png b/docs/contribute/general/_assets/Generated_release_notes.png new file mode 100644 index 0000000000000000000000000000000000000000..e8e86abba5d6e1bafcb859e693d4fc0e953758df GIT binary patch literal 55970 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 ?G2FVVp^|J?1I#`#FMt<1)}H$hh6@Rs!E#7M zeCV~>A3Y7nq??D52)Q_3wm8zvHnN6ZsYs2Xe=Tun!hcS(@TDk~ozKaXn@KhbT0JTq zM?;pS)j@$_4t~BY7a7L2gwsim;?IB`^3OO?y0CZR<z(l*$ED7?iXZh^8lvVi>L@UE z1gHI*@$T5h`WV43uiCdw#i42et8K0<JceuqO@FF}aETSW>n#UH_WR{P3Pr@Yze=nV zF@0xjl%y060kc-)vood@Z#AT;)PXek=lHsi**t228fSw$BV;Lj=LLC`J>RX2YUi9) zN=;^BrXN=NCG!nk-@gC;Pu^1-X>wEt!M~S4i@-YC?9T1n5X*ph{#1N51y^p2Rd$>( zjgqrqGgP1``v@$kR{bWWsLJ)tMd!WD3){5CQWhgdcJ=$aZ@Oj;$g%GFQU+1D;w67i znZ`@p>k?w-X^Ze579X`o2mX?o@i)z0NLS60_8C@uU(Kg8OrzrdU19CHhFM7JxMd`; zpn*sQ`+X7_0mC$9>bv8R&PjN#zyl`W?c2Js-n?6pS&`-9`BAneW_lB2kG)Y4<fldo z!N9?f4ft)^{%lumV*J579K;enQaau|&U!}P@t(L`@&!hN_`KfO^spJ|<MoI==f^S; z^oc2IJw6!qa^do+OU&r5DpUfnr{@O)GQ3!mvK!`rk80){xdR=`2lfDdf6QWgiU?_q z94@V617AnX$n-KI>AG={3OOKf9=DLy=>Ru#uGiPs^&Qi)N4c1B5ABZ<1=L-Up~7xo zuMMzbtOBeHX_TvAPB|BECvupjPDd^B(revne&P(%FmjzJNgH_NjmAE%4++4Ya2}Q^ zKVQUQF5g(gMB@M2MpujIVb>Txov8TQ((2?yOL^b<@j)IRV4Gv7QnxWNdfN92J9^i( zrXT1>L5*|GL$%`(_DZjt4Qz%51@Jl?3=GRupoGfnL9q^b>;9gYc-GnkmdMkJ>%A+6 zSG)XeO0S1xXbo7^1AUaxZ;#Zyru0W}g+e*}8ahtKTHTXe2}`sdRRGgu9ORnIU|r_G z0WLm@L)SyhFt+)jf$l0QowZ-~i;cLx<Hi&qYHC{f3Pa(BUohNsuS1fHnT4Y{D<PWS zkbcX7pL<tVLzF}b$4@m$7bfMIX7Wh7i8pOdmj;+Gx6XWzr*33HjsydS7ECh~Rs;v# zFUnItoGqE)DM^L!5747a7Y=vAVLNHvdVS;^9fSmP2@-c(!_(-@dWg3~L{zX)#iFn3 zM;f_oeg;CX3qPTITK}YufV%J)w*Eumxgi+dAk5*26E~?@$rn^Oq!r^fIVJa0!N=1N zG8WQ|^sHY~_8r#qnsvJ$ogC?#dvo;pHnu~U)h2enXu*0?+$f%+A2b;4@#8v>PUTrg z^wbQV&emW6eq?o$uo&PqDA?O}C%>-hz1@>Z_xpWU5r4eRw3uGJj+qQBqK}<UsLd)* z+wBdW(z`VHv8V$ADdrb8v>Odn+HLqE9Tw?(JWzAEpy52&hs}{UkgEO0JFl<(+$8a9 zc+cZ5TP|@w3O#dZaecsdP$8f4sy{$9Eo{hiq{js&;-lfm63%ArN(ZEJ%COGsXj=Ka zy*btYXrSF=5|c0V^07z<k;?|NOLi1>!#2LdWF=vJ({w>!0V>+}H2Fe&ey5uQ^p$I; zKyvHXAn(t-hQNLYpc}ZX>tk20=3S$8WsSSh1hWo8G1@&FPp`C`nrE?7Obz1B$@%W? z23&fFX{)HH^^E?oQue0VUIw@AzV~zNKyp=aWi*yBLgupixDTh>Gg(8Kj;4viu-_LB zmA#|UTV|VxBvA~|4MN7McBHaAli2t}icw>1e$n@MQgLKMij@5OP`|l?DXD%G&+EZ_ zLWr1Zj`k%n;6vbRR7i4&*DE}mI^(i(@Zdx7)zh))5S~`l_l+wF7UkC>jU?4+8xm(v z)<kta7vgMBokfLl;%nBzeO?1MrHmEalyUt-wOBIJ0+2>k)A)0bBK?3yOHtML-9xUr zRNf_ou@33P{!&Go&5Tc9b&PwUTTaa}AHKQv*%0sKE|;tcC--novo{wY^kNqzKHb0l zf(^x1WfL8PFmev2!Pt#M^sU_2mB=woC!fzKNFv74uRaNBEXfN?`f+*stmu)Zerc}> zsW)O!W&6Us7VoKO>5OajZHd`i^h^2skWC%MS1jBn;?mc6v7{8yeQVdmprp;Ul2Go; z!5!TjTEEi&Z08x>&9h1=;ebf)jM}MWb3BB@>w1tjV^XO>T|l;X<#b?86}CloW9yLK z32VcHa=&5@I*&?Nm6u`0zdW)$xo8sUnYY0g&^i_3^oO=;18WJZ@P(;diX^xEwmant z_1Z?G2=ST3X1Wgk6P-5AQy=}~4EV|Wqs&sd>eUYyemdp(w`^%_w300O%=(Z{%wh8y zbamnO{tms!Mi%?!)R@>c-n8b{AD*;;c^bzF#EK^zp~u8~QyR5~91RyeWS$c><7k6O zF;U;rK;5EWkJ!sW3&w+fTRE;XYJZa>-78u-k7<Cu>tCB|j(WNT&v#T^CG*2ws}Dul zXm>=F{=DrxAqw;)J@wmAdE$BoZrBd2e6Ih2>l@M0mAKCqwcXVnQL<o3Rp}$Vc-{UT zzM<J|pCZ>C0~+jmBMBDYtx)a-l*%zJ(;{9#<JV1eF_364HR$ybX}~6t!9vb5CEJF5 z5@B=Bvv~tXCS_N~r-GJQCS}&Hi=V$l2JNL3Yljb_C%hguYbCRv94%vZ(QEuMMFjix zZjsjj8D}eK?d$R$dh7nIFA>{(MdkOQhRy9=n&TAly)V8z2%gynUcEk8)&^=D5pS;P zp7v0luIn0$p|AVr+XuYM4sORKde8#ujw^odiGiCzvHv-UqxzDE)aP#88Co_iVO3Zm zmF!RS&HwvYPg<+abtdAd@duWnQN5Tswms+(P3Ujssa!srqOqD2hjCgW>TzL=s~KqD zO5gRTHG2|Q6OyB`hH5llP>V4D@d)AwRo~yR%uAvPuH=hfB`nx*)i=jYr1Xb$v<y+I z6>*9XoipnQK)v1U6z|1+`5_CT*PztYG6xQt#oV7|#DH4Jsq6^3NTV3!#NLbbw^l7a zy=s($7jGXIU-=!Y!th7b6OP!a49lQOOq|i5GP?u!N^#3&GRuo;q3PWPTS@eOOvysB zv;mfFdBoKQ9bM8Nu@uvu^5bQ{ldv&$R-+28$+aX6rXG8JR3803q%<F2d2-Fgh(V1t zzs_zI*^$7SnKenL65u#cY-+L)fo_u;<8y5*+HS1;fY<rrfzRHBgv9)pTd$05E#m=^ zvP);lYqJxh@43F?_Hh^WY<|0OTb00cYcq(q9vbmD9CY0;%Y+Kezgx%tu|;QU6tslT zCd%9@^oVj^6%?*I*XDU-MpgMJSx2`I`xho;)CTsM#%LBwoN!PH(P5?tOPf`Hrc($! z0DXIBTZfm}2<go<zL+l$j9I+LUB1Ekqi80=_hNezq<Xnz{q)m*Eo0h-$mXW$Gxg^~ z8)g!7G08(vpD=E4w`O`H=+lAn?)J8S{)^b_qItsW4&2DN_b+S&7Wvxt#^bC@X7H2! zF;sv0kBuC!>OVEzgj9X{T+1G0G2JL{S}=FB@Kb^5;|Z!MWouXax97;*0_gkvkpZlV zE*Ko;95n7?()@jQ%J|nx)-Q4FOic-7!#`bfLuD!wTlP#!v;w^tbtjaM&&Lbtd~{Ag za{`rm;q1MIJs4JjfA}u7TbcByE!vECYSM-p0G8(j>Yd-|{}1NgDypq7eAjJ@7l-2R z?(W4Mio3hJ1#6+j9g1slcMAlHySux)1ecxu_W$fL&N!FnX6JU@t(C0IIlt$9-sNSw zy7Czvg3G(1`x+h#PQf`()^H11`fmrZ@{RO0*ycZi@f+tz*2iqBG{MKWR({5^J2>1& z(f6kzy`R7xiAYK#YuVVzww?(Pn}nmct(qJ4!s%h!M{ciQj&af=56U{fK%q@sS}?VS z!qPU16ypP92hjuyYCH*!$A(4~_dv?Q^#*PakBvJhK_Vx+k=83)sE+x8OrZB+wfBRT z?V`7V9b?*kPO=U4OSys_PF3UR&G7*b%_e9k)Z2FaLp$S)4_M=6gWlgY14*Pm=-|BT zQ!6l~%1ldO!Zde1^hZk_xeuNctWJcP{m{|%EAc@n>bA-V-?H)dEjZg3SUhRUt+On4 zYsdyB#fv9r6S)KM*P7p03u6V!Cw7`Zm7gg4TGZ{alI_D#8@)@BF%gE8PnTa4noV8A zxEixyMN!-0*~;ZnU75I0-FlsRZE3&ol5{g0{!Z|0fv3;5p$8RDntJJ~GGpPICFkNS zm}|#4zL2>5_ekL1Da7s07XuvPYin!A2A$aUW=T%J(hq#P{>Chnqt=}srF)|6*Wuay zH4^3>RP5DQzjfEvImmD3ihLzDO^FWQd!5Dc7P9w4niRFrK3W)ea}zER&Sk1F4B55b zh$ig)5Ki6_$`rXLULOw=&&|Nti7q0z*xcL~K;a6FX`PgpyZ5C%M%UkXD&bBN49L)) z>hRVAb-b06*dlWsyhQ?-LX$r7)JkKbM?H^BmLu$uv|jW2Z{6jXzL4@whsnY5SeJO2 zkvi_ZgC29VQ+YdE@grVXj7E-xROUv)2TRUlhwA%&O*FvC+As@>t!hwo--ceP=hz_t znUG;v&U*Jf+oauNh0Bb%d_-$Gi`;n`@z=_d`VM)JOP#(nbAC!hE!UY>)dCl_u5bEv z&Xt{s^j6IZdIRURhuW*ZUT|N|I#x!?FM)GTgqCs9c=f9R-#oV)=+EwcbZRO}d1@@F za+Pi!%2fyy9`DaDlsmX0!_Dy6c3yPyt~YLg;rqQcuzHgik{>Je{a;_U(N4q~?-Klz z;f4m`RHz_9JQi<V`o<=3!we*vrc-uIi;6r61*b-qFyFFBAi*+u<S^406;G~K)Sn^G z0BYZ?Rzypmi3Kq{jH)glut9g|^82C1+I|e%Z2mN0VJ2VP1DirZx-V2ynB;fuDZMer zPN-DV#^o-~h<aO#^jdLV&`@L80aVVMedpHE7{Z<JH)!-+bq3-k{2V=)>+<y!>K}70 z91-)fSu<*RlNb|VoksRYTitODp1inh)D(K*ep%dt3N7J*JP_$*zZ_bjKUv@R-iaZx zlq}uIv@|fQM0Nl2TzRdqDzv;$skXtgWL^tAN@HSu%lD>PxVxV1xf$am<b3RjqXfr# zVERGLhqEAck3;PPDC<h}MO%gBox;6`uNmH$M0DMvp;Ni`--{Ne2t|%v&H@oddWT`t zkYN_J9Hn$bf4~<QI20^(`>Lk~d~^zUX(!nqU63y-pDs38yrl}u5yt4*PciGR&h9h2 zMvlLu76w7Pn2E=0J0tfa5L|{FqxWGYGviLhMK)-Gx3m7@O)*1bfJ^MgvG8{lNg2r1 zoO9Kqn~SV;_fm1ND}A6c)KOWHpH*vz=K^kh8^)b7V#=ih_KAx@`J7*{HgoX@)}&s? z69=4sYCC#o0<bb9(;fCsmF#Odb)%5fz?J@JxCLeWymq`xcs(IJ3)RU3+OZ>1$WEnB zhP8VdNqmd?8UpMYC%w(WA}wWh)6rfpDCWv4%~r~l(h73QW1IZeC8gOVOLNFvS<jzC z%gojN1&Et%L{~%J9|@m#1Awn6y#CN4U|pnMUy7xyg>8LKPOr9k)I_an@vzWSeuv6P z|3zZ)<rhWTR_96&n~GLqAG#x51KSI_cqS^HATmZtJ4*UCd4&wzh=&T-2FDHB=X;?L zq{mlVIj!rvDfvj-arI_H&rTg}N|pz5?aU07aM<SryvJ{GILQ>ntqfJRNrWX1N8*dy z48PIwtTj;8tWTQ9{*9j&QS%5ioZzZ#8T-pDT1#pl#W-x)4@hNCFa^;gi8xJfW3rip z!tDkbhI>VIaClskPog=QUiQg!%(u-a7|V0!<m&{@I9wj6mL8N&2Zl|P^shy`?Vf9? z`BChq$u}LK754gQpSRH!0<IJ@7jftGSr(}@qq)hN+hhjZiug<6?0OJ8g6C*I*FIXr z-%055@XY?9bcji&b3Qz!ri@T1H~-JRf_$l{y|(JjA>x572e6!-{Ft@Moprmk!ocSE zAah10$Oji8`IkBrvb^dyJ2eF@5YbWUf*UAS;21SLZu__=(m0UAbq2nf0Y4>{5^J<A zn65@CfbcU<Jt$fWv&0A6t@MC7ndrZg*5*n$jt-b^aJ0UuF|)h7rDzk)Fypc!M;4cS z=(OhRw>{`)0C+IoaHSrXyRh2vQCIR6P0Xwb7L)lj@lz|bhCRbAITmV`i&3XAUHqa| zP_@Aq*CO>0JGlwA1JbYEihDm1jQQX3oa%i~6RIsJdLu{*w0e~odzX4FY|1HFqDv9! z>)d}w&RO>2dsy>$F<B_qruJIPB{4bbc`{$yh<hV}fVf}MJA0d$jL4NKAKD~~IFqTi zn+ajJLE~IW6-sl!o6kD+z`_+S7ZV){`A7b5l6&>}*B>b;*tCW7&WGTkZF*z`cS(LE zL1{H)>(t?_q|`)UIxYuPswCH5eU_WvLEmN3d)E_Y$@xZ;<K6s0FNVKrRP*Lofy?QH z?CfWHDN|Q`94KV-F9uQu5SngeJ3iIyk;$cN1Bjg1H`ht;Mje8j*wrmpP*5e&?gv<} zfu}tG^25t*)4IE(PsQ{}CMu&%KSTKrmzCGLa8LrWGn)0GhyS+xa8?(jUzu%TFz*-& z;^D>0`q`Hg`IU0Au0o!b?$9MFQL?2@Wc^Gw#`in=v)?$hOZNECEPx1)WGzi9y>4U# z89*^qe}Z1$@U0>kUcK1q?+VuO-OCV9Jbn=zQ%7y}W{U-&&(J;{%XmeyK>o?BTfO{g zlU$r_sV^w+k}sM0eD@8@#wk_C_lHW@#1Hs&Le3J$FL+Up$sbrg*`<^@9tnPmdtuOc z*U(gvz38?zaGc(9aLeDF!Ih+T25(cz%!cgAj9~uA9G(SCj7t@bHt0oZ|Ds?iSI{$K zLMdYT+d?CTek%b@EmY0^hgdijWEQ$E-O%^f+kE(dXwb!t={h@B^bqs9oob$i_RCJT zVPpj+k%PX&*N0;*<D<`O1zCvVeUIJBzP4tQiEJ_oDX0z88(yJ*XPay2bR9Z%mmI0& z>=|l7y>*4!WzmnlWL}}iHid~m#<f9d@Wtc=NL2&qVD_H<wL0WFI9YY?;tlS1ii7-M zTd!9%ulu2!VEd`KVEZ`+_S=9FT8?4lbIL2$)<Eya>#s&hFC+e%6J~Mg4eRP5+WwZu zK>U|oKFnnQ*#aTxlHHuZKl_Dx2vApsMO%mXltb9ZkgxpO6FJQTb%9BI%lB4INeg(> ze_77B3RG*U;EHCtP*^BIs6TN}x@_YYu6OF3AeH$cuX}QT73dexQ<tBPf5#g>(mfoh z-xPoQ>pA~`2RDIvX^cg{$`*$fAo`f#2iS*!H6Zunemw+eDGTzG)8*K)wtw<xW8Vqh zTDd1cXFL@(TqjP_KZe?{j&J3?rq(U<A3j5a33RzC;ZrFYO9|Yk_Zy%lzZu+`7y8g} zwGykCSp<WZ?J~u*mfG5F29MzxzL#|#3{-8c=v#&gX~_Pf)G$X<{V}n)46%?6rQYE1 zX@V^OwAdTwQ{Mmq3ZwM5RKFUv$}!BliZm9jNQ?F#Wg<aV?wQ$n=r%TY?ynyinDNqo zHhWcf?|v8wVEc=U7CK5^o5ko6o{=V5<iX}T8?<b$50fv0I7a1dpi?<wz~A8D_!Gy{ zX{bM4Qf2wEM>R{E9qCe3rh>O0MPvKncvCalL@1wUQ(}s{KndY{u|_Q6^1*f=Uw%89 zUC>z!U)Obeuw?wU+q@AV7ROIo5%YinU0o0EqKXyPZ0zm6=3df=xZz0=b*Zs}KeW)3 z)WMT0_AT}0+JrFB;n!lZ=86vUMy@esdjpQuUA60Cqfw~41u*_#eWU6d4BV4ihE~db zrg8hkVW_kJi8xc?aI-JD?@7Kl&#<c4x+Lri?$Y}#obtLGL6zYftdn|byw*L@llOXf zlFt3sjge5;fZpq_LF&zH)`O(c=1eSjf)L}Nsts;6+-SmXhwSU@$=W<+$(548f2PLc zL!G!V$Hl2VZ|eZEcAT@mt3sl3lJ#Mn--FtMBzhIhnIRv^Khzx8_Svh({!K<c`0Q9g z8S~Fg81u;R#}INZ+iY&8Br=)}fT#oAl|Li|J`<0VEQic`KMN3<vKsvA;`p$2#SjOY zntMBkL|F&%lEW~;nkjDR9JWmKkVx^6fs4WYcXWto@E98c;~f94%A?%TP|p>yq~U;s zsL79`A$mwKHRK<aU+bbrPgrxAmkN0(h6G+7!utpjmKUKxE;3wAa`=7-#u3BNBy+nu zRB|VQ7v#DkaenI#J;p+x8jEjdM2LLz`UBV_7LhIMTG&{3E}6;q>lniEKW|Y4{aKHq z+Li#xF7ks=FUm}Jna}jm{-p|qpydCb_$}o6zt8^_(#qKoyOPCL!o*LnmvPm&mb-tH zK;l)rA(X9af9hM;9N}lS#=fOs<vUCi<lBlldC(E;m;+^mi>SZFnk?}^WP3_%Xcvys zDJL{k&s~9({bL5P!6~D*QupOU>A|TupH*N)ehx^H?b5iG;Zd>tjIcoYs-Oho&JjrU z9G`90+tf{hWSAV)Vl(kRdRsfws>=C}znx$&*tt0GU?>1w&E<881u_1GKl2YG(vSLi zl|n(Id-}cBD^`@6DdjdB3>%$hz4m2N*`D@4O)rf-><9nhDJNRw<qg>To)ZT292eGT z3sJd8BYpR?k@f6+rbG7pguMZA2c-=aW+kmv!jp>s03XU32_78!7Z)w$C+6}Vl36?b zH)v(X7c@kM*^?&D7vzxuFxj?p=|ZJnXgP_0M4)1I->WRipX!J8j!5C&o)cyhJq<W+ z=eAC_6BE*NW=Puc_F7du5ce$rnTw__9+wZ<rWo+o1`HsZo-Y5m!)e~xhO=Zt5ZA_q zvVQDvU)CS9zyO{K(ck@joIh?LIyVjuBWS~>vW*a$S<){Ui~cId!a{U94z?~?{h69e zOX)}_HAiEuG|^9@A6#08tH+JA`XE^pIg{7ggsU^e7B+Ogu3$b^Wq-H;v>RL+OX$+m z6{o7(kKB9?$1NB%>oE_x3LyC@5vj0C>Jo)p72)<uTp)z`tE=Zv-1HJsxel?__Jg++ zbkfABX!HsqB_NIExba3^^Z(E<J?`>OJtw^Wr3kp*Gy!=<oB2+c(yKq>V@noLxVE<i z0!25=CTh>*AwWtj3x%IJ6u1BC&u5YrOgE^D-o*RW5M_}!*pau_YH#vR(Xqp*$WAvz zQ^<|OWOu&4@3ZBFkRR(k>k=aI*mm(?Q`8o4K%G9S?tldOYObOR5`5qlFY~;*>4iND zS7n9<4%vGG{7bh~k5>C=V0lXxMxNW^n;7>nGoJ{$UyT`4ozm=%9T;fV&g!d0#hfh? zbIY0$J$L44FT}t3#8#1>5+2d{OzP>zHl7n$%_o#oTGsz4UQO!hjAM^jd{pBmEbv4> zeW#JXbzv*kT+-k13H`x0TIzxHs?M0_x~&y@{1q_H=BhRanc=B%#CxhkF9dJLy(RND zYYmy@qqVX??s9-jRHip7&cuI7Fz+`Iwhy8>I<ScF>=zwwQW)rh7-xfuy&%J=EB(RP z8*u2vl~g66kWQaT8u|&-P_$^#G1+8{Jf7|PsCb<#-|_$hT5;k$87Z2~9!n{^y1&n0 zO{c|!=py{@wiVQc7zx*2Y)S`Al$Y^C>>M;f^uz5bO<3U81a93-lt{SFiYGx(&I_He z&k_z69aJsY2-fsn*T}EqCG_D}80Wk9p<DYF>)-Rki&X$_*!>scSG3f2{Q79q_9sHy z+tTxyMK>qU<g;ZucKTOVvMrsc6rUeZ)f5+XZ^Ry`H|XdJ5rbVECQ#Ef-r=WdOu@>~ z(;UD}@|ob7ypdrq3VCxvWRojxK`F|`e$!L$a=Ws#Z>ZDGNV3Y+5@`sR*&t-A&zfYO z*6*4FAw|`w-6@dS$Lk5&Hp1*)ubHK0C13^tl|oSHxo2hsbqkZ6Re(#+Pgs^ADh}VX z<4tIEvvpj6_R~(EXFXDVN<`FD-o3Ns!e<8(>+z~i4-QU}f8f;j%^&Q8aq0+<-${&X z(oN4y-y{WJjsq!_3l5(B0)FDW%o2<XI*T;D%_uuJ8>lZGY<=`Ld_HZa^*~#6fADe? zMe04PnDEBS@9wwt7~Bnf1U};$Ck=!RFzK5@T&%HVP77S|k+J<rn;#U?$SJPmP6fLE z776%!>Qpbg+^;2LP`MVFdohoa@8A*;Mg5gk(cLfjlMBBM6mO1#c;s3>Jen5cLqs|& z<<dPRa^)+#9LTMmbHPVtw|lxFmEwL9`^>7*Jjpw+Znl~FmW1dV?WhGIneMx*5ikNN z9ep|WWqE$lA`##QX0qlj7Xo7ZML4H7TT)@bc>wgwSH+8(l_}{+PN$yOi)re`<GPI_ z5N?>>V{zJhRAt(V%KJiW<HB{PA5*bcWWD4d&Q&xSKL(j?!uYhYRcj*uxI?E?hk8^) zs|xOZHGV0y6d7AN1~Pex1DH?VZ2Ixn(}_Rg?Sg5|ZPjF1^DoG8OnCB5)R!6E6l3l$ zj8pq0?G@UcuglIzbosq6`SbaIf}1~%Nw&qa2=CzW5dGM0yqM)ZgVw!zQiAhBXFQ={ zj$1wv>n-=Ft#FgAd*ctt;fA_C&|7cT6*)1)!>`VxWRi07<MO6vJktPQgxlPREj!cW z$j<2DbD;##6WhQMayHbRLRo>3c)d3Y!8H$mF!+Wz^rnN~WfbJbCHruW{c*gXAFSW) z?r^*gHLK>oGcghGNa=8$Bc+EIWU&jCrBUKc=ly#1^tkm;<|Lp$$v}i)HDfoiBW2P{ zh))N5EoPRxEXg-sHMM(S(_O5vcf)!#0kN0+jF6?e-UD@R&%?;+bOXQ)APV90WXeKa zHQ}6@HD`Vir=EReShBx>H>H??1GHfWcJQ9n^5Ncq-&dj$7HtP;HzAZ^e_I`?$2Zzq zRC5nP2BlbZ9FYrrj$@Px=~cDlTeR;cGmz|5(qKDJTTmw6(?tV6cRC~;TahVExKjmf zu~&V3)Q$T~(M|%bN*ODB=1!YH&_igLe(ud55Sxv6Bioy<!!FJc;3h3CZ-&eYdA+rS zlqb8BO)JiwD~2^IAzt6_dHx;<NgwM5s^m8*o=%`|r^>mwSE=5bO_r(H3f$Q7w?vK2 z*1_liRHpGmS1xu?FrG<0BJicDP?Gs+7azsAIvRz&U_wl%yA_Ep%)4ZjMYtC<;huBH z&ZdVw+T*M66^FM(I?-o3`nrvDie8addQIO;A7=J_iii_$4v8ZG&<CpRY)dCfT!o1p z&!6_Lf10uy*9A|XGe2h;M*V0Zm+#mRIBH3&$_!AG?;l(Erj;Gt@|adaz>1t!E-lcJ zwS<67o{NCr2CYM5YjOw4VlLXG3M%M-;jlDSmlHh+etI+Rjqov*E`8d7nzLj3xmvAk z+Xsn8yfLA#Z;Qp{B!|<Vd_R6-D|pqb4fp|I6YKn%ML$`dpg%6T-sT!qUS+(YbY*ZU zc1r0Xfg06skGH805gyh*6<}w>PbCX!Ys6owR)cNsBk1m7OFalm#y(uAB;ONNRzt+s znCLkMmG_>cpK|Veh2lm_hOud8@lGT!tDPo>@+C-pYYBBCA(0iO{;C{(A~z2qe2E$? zd_m0e`*7Mx7BOF=dA<MA=i8rBcWlG;7X=v;I;ouY#wR@4!bC!_>OSgu@*M{pRu@X@ z$esFtAh1i=ZOfDP$gh<`cW-11I|*1fNFY9P?kYCvLi%r~%6o@Nz3#H^E#8+>f6te1 zAm|NNbt5l61-w}}G7d`{n}Yq$2qL&Vav~C1jCZ*4?o(s`1O^EFz)L$FcAq5kV5ip3 zY9aOg!3c6Po+Y`BO`TMrATiphv3;(h^3;TJQgK#}mth~vk#`PG!@VB`)G}3d3n&;h zUy_*u=i&V<p9?FyX5vZjZ9IO!Gv3NJjq=j68@du<Se8VSmYWIU{g7x?21(g<(#<r9 zLZd$x2F@SYj6?^lhb$VF?w|qPd5+IfXBI>@mCzA!Ou<O;KWwU=rbuet$Qx>3UX|F} z%7{KwkBXmu@K10fPi*4Ql5bnDKOkGhz#Z}Ml_Rzz_hug?4kX{y%ZY4R1OxKAJ}B3U zc#us^E%R;oHGI){qQps?n$#zP$Z(Gl<uxP0{=%44zrofu5$IznbG7sHd<Sl|tC(}H zdcq8M(%HOPe73v#`B^KyY}!7Bdw$kwf%P}!PveYcBah`6)FT<>xhc__S`+YCBMVC4 zZ0?`ZQl)IUr%`9FC!OW^8-`7v9|)>)%V;sf%}6@)HXQrvP?hdQAHMh~gx%x{Qulg> zFD<V7^!!1!6nrKXe&XTt-iAqwAvq6qTef3+NksB<8bFk1x)BWH$v*5he$eA!HhlPk zXw)8b8?sVsoK2H$-g~62hV!uV7-?H^|Fn0=rU>N^iF3qVc!g68p>!Id<R_myK5a5^ z<wQ>xQ7sD&DN4_M(NkJ~H}{$u6*YazEmb5?;wcFqK9E$D4`S*(+w^4`dDJgWpWJ4F z<S#Cm`2JASLQe1HGKAeyWEE{}pNxBW*_cXfhRDh{-pd+n`dIqBq#f;_HZN?`8HAUX zI5n7OQlk|~%4Dal+V*Wb1+2kswh^GaCL^_(se|3;$^}`sD{xWm^-V2DdJ*h|({jMH zqu%GIgJN!nX1*`87bqlioVO`A8J?N%x{6xDbk@4LXTiBe8uO9s{Y?uER{<F(CclZf zSC~fT#D^5c_q@iJ*KX6&=c~#uxGN)O1D$dwSkn8eu#fKDz}e!3iYFL`PJoSo>}qA6 zN&<>bGshX`XA&nf1Ey#H%_OZ1;ReI3P99Do?<x=7Bt{#r(>s2yzHR*(SO>g*E(hLX zYMt7b`H~c(_M@ay8|jMRix-7cxYpI41y0Zo?W^8&#;Vrc$$Wcdz&z)Dr~UnwktZcj z<)YDodCG8l)th52_j@jmaycEp^uSdp%gD~$5I{G1<@jMH_9BN%(SOa+H^Tq&&1S_W zCMG_{Z=G)B?lbWmC%LQQj7r<B2l%$XDBM-=Y1Df8Dm?u`LuKaEnYQ+7!$cR~{VPsz z!=7%<Mt~i^E6`@n`SCR|oqM4~)|7?NU+FzYbRxoRxGv}2aHfGzZX6<u?Vz_#XISVO z2=HM%U}lp5t>5BsHKy&QCST|k(zI4ekIFeMdlXe2mFfPfwu?yD<RqzXdhSZVZV>g` znDimYh{@*R^1stDm=R!^u=be{9?RCx&*5p9P_)&(YI9Qzd{pqOI@h16GE%gC%p^RG z*@|J#U!8ag_#$p@JM#noRop1>&T%G$E=I%*WQZ~mK5uI{Hxo}-k<!?I>;)HXoBr%- zGZX4c)YtU5>1CJRkD_w%7-g&Lq3T~Gl+0<@teBqSHOZ1r-Jxsd#u(_&53)(R6Ns6y zUwNBva6kH0wB=h}wxFmu=WCaKuKScy<O&7~!8IFN15cI^72Q_!rPXHi*<v%5Nrdh3 zv%xNEdvj9YfM@;ZEIq^<nutRF2#zz*h6(o?4xr2W!|`WLQ`K)@rsbSAu`_;0oE_<s zto$f%rr`Tq#e5-zzSv-pZ0eQucXllG3?ZqoIA0=pT7Otd)lvv)%0`>O2K)?3UcO3j zF%!!LbuxfyvE*@_J2;BC77h|25ph;SzgQow^D&1C_cCIUjdo-N3Vv-CU{};77lgYe zZF?q!`cq@m$e7j^l9_b|esSGlJR%b`gTr28iezJl8M+=9^C61?>iR7G^TuuTtV2iy zyEqWa;BC1Vl;(l6g%pK{ui&Q(6&5C>kE!gU$$lyM6>|p2R`j)eAi_(uBX8+H5B^*_ z*N353Lld?dDZ`)T3@ReeLiuiP6OLcR@2HftoHv<tE=WHhaPUtilmKYzb``lhd3$vO zM>#&%V)nj6Hn?9J8yAQmxm(R4dGPdV!u9_8cdqq%BA!exr6`G(2Pa`4;M#hspH<i^ z#oGebm&USV3;N|~_A3$R^@{x+WhaJ7R1uQ0bA9c>{)3O6GlVTu6DzDfrf+u|@Xhi@ z{og6=0h$3?RCS)E{wqA6>aD_dT556OPM^7)7zaB1>xkqCEv1*86yc7Qcl;~e=TYAP z(M+|BzXlUF$fgyJk8Q?48G~)1TP9BcpN$Qp=jtOn^*Np6t273LrYWSv_DFsYiyOBu zemT+7VNY2(G$aE<8&zK`7OSq8$!(BJa_W<wH1kiR5*v7E5qz6z$o#$qdIJDt=0~0d zp{4iuF?kiOHH%R%M6G4BKoQFeMu{hP5$|%?!djbO-U3sP!l#Su5gWtW)f+Gg11}fz zChf6rWWiRf2}TBmg?f)^XPs`1y^G_hglBeFZ3J@{5gwT@#{uRn5EQC4#&qRD+2~hK z8{@(h!{Aa$8Npgf?a8I(pV+Zld$c279Xr%-QFV#SlnVyj`TF+5$sy?*n~;rS{n>Dh z{L2RuNLu7~4=L)Zmlo!m`qhTF>6%f^QMcm7Ncn>4Kg{RhJHA^5=w4v7=vfRj!cz%u zs>Rls=q2sh``(+ToAi4GQ51S#0iw&(BjDH1Y6pgewj8!|BKL=gQCfVVVDT5Sttc;8 zMVo`kY^fQGX%c9S{2LG?D9Q&c@uaFg0tjuyT!-~0vBfA|Z|~ycMGv{|o{pW<72`|C zM%-?q|60N%vY>q0sYQ2f^Q6SZHvh|M2Zf?VDD5Z*E!g<o4?%38N+LYbccU)bd+3M0 zc|q0eaVTswez+`o&perxyvx^sz*~0(&!iSuB<Zjwe#n3{XPSAU^rivHpq%v975#4L z`*NY}XC_+|EZZMWn^D$nNYx*AXpXyXyIwWtTuxzrh2Q+ZZ#Kncmq7i=lBR2PYaw)X zZMth!DLq{09p%gZsV6A2k;%pQFXw1{+E4jkag8auVWTplh1k$KIm!XVl;tI1Q3Z=B zaCQO#r)!4?4oK0Exi;5Gwo^m4Pj%b3m39!*T)ggCaN_nV)pYXx>CxB^hYX3hdE23h zh#i?X5_)z~Pn&+f*Rs0}-|vN{5sht?$9^lNhOyt|*LJ%;!UF)HdGSbdB)!m4AEpDz ziI1iv|8OSNcrqEi@Pbwq_yp87-I8T}c#jmK&?quUr$O}?;9gv&hKfcf7Pue#`q82e zn9RAY!|3Vkc$;IZXKh+(HewCd!|damd27MF<n14<5`}>X*3K+>iP*zE)bg3^7hLvm z;SR?0>f?-cyj(hbj4YxYC1kW~g6)bvzV+N@8m?L3@YApw4HO%dZ3UgOtU^Iu)GD+^ zOw0cj&-U6Zv&eow4}uwpWxF?e!)Y2eIih$t<Pm;&X(ibj>UX-Tu71H{nUC1a(KY!8 z1-Z+=vPv)eb}|gkuPo^z*a$V9I;(n3Sp@cl;`EBJkUa1U)NVkB)O@i|pC&=(laEvV zAC8iT_*W!m<~mF!<D4!N0YH~oW*O~!0o1ZSZ%clp93>&1u*BTWS+1xlNy(HZqtNc` z!VZW3DK%T3Qa>>IS6FkvaL(N1mhobGo`@KRVb@TEX@N2t&f<tKn#e$v@;YQKT?&`g z%VHSG)E0T!g#|^79ARJ8cE;{9HG5aDL7}ul2CK&p<oBmQBVc+PA)Te?__Gmy6uMMT zuKSx?U`{)Ra4w-)%on5b>>AmS@kAHV!2@KY5xN*sxO;9JtQdHOymtbIOB4h_%N{Ka z3aG@EzrM1XL=;B<WI#$4)W|+LJ+3LA_V0<}RcPYR@mAXSt~g~HxNt7Itp+(+wHKWB z)LP+gcj)=IWR8u!0XNulpi6R-SS5$l!+mzHc~nX-?C^rS2v{s_D>z1M)}^k8|8pyl z-A|%hShVa0SaaT?@SfdL^6EYe9b)MS$E*(jzCiC?HKg}FcPlUTcGR`N;zIN-T-RmL z4{Ar~tk`%-@{fEkKQ~;~^>`J2<5o?Q&O)9=!yD7w!-i*=SV;T2Y?hzY_tLwGF+6&s z4LC5m);#*_)><Z9+1x}u&)||UtM{Qti-?_dr~Bh%Oy~BNQK?Ca{m-Q^93Jf=|8Sn( zVMD(Ir?H!dvnh@+gA>o&t5%ZdgFDfjiw^Op^NGt+K&UP&nwBOdOV1$bKwp+C(63Vf zxBGTwke3C;+F=;^*s67J$>6DLWx*B5o*SEIhaZ>}9$6?Tix1nNeo#yF6q%Tmx~2XR zWwoNJ*wL~%VQtQ$u*Eqxc8=hhk06tK*yC3hVr|BT7?AN$u#Gq)BL`qB^-sLS2Y^|J zym#-~uD6(z;j${kk9(7++hb}R-H*H{3HE^Wet=AwM(`kDWZL%^5YsHG|ACZi2&+sT zOUfr>T?K#@>}l+&vXGHd$EIfK7nNUo*eI5nf{KVf;_Q0QAfr4}p3%an09|6bq|n+n zH}jRL@c9)@psT8|Ogc~@;E{KnWGQ5pE`W6w0+T-CA`vux@TqDrXq%ewN>W^~hCJ{( zD}qK;#%Nb*3A3PbFA+f@jT-;LR^1`cs|KKBeUfn1X7`>%Wk*wCuW;D_SKR&QjlYFY zZmb0_T})mCXpxiQ?>?bZGU~moP>~STG;VU(XtM-=3EIuP`nCcvfTn*9u+FYqmLm%h ztXP(s&H4&)y{qVN(1*g+YOK@YoA)04+oaUDGy85XltVTt5fcY563?rOY`4s><4$Wl z+fmYY|4yU=o!)4$smGnFLdYS>E>}SF<FLK&cE?A5b7NiqDvgWJV~+hjs^gAgeo|af zYTK+!-Y`BB)pIA28(}AXgYo{Mz7od%D)Ju0D_gvE7Fo(CfLx)zM%V+PFZyM3^4%c~ zDz@uXQ7w9gm7VxOiwz#+yl%pavsULxZ}12+odsp{s)Dz0gsV(JL}rBCg^IzQ#SZ;F zx3X}N@ljHh?#qJaz#b24yk4iH9Ovj`zFr9Dges<d<YlT~Rg_zsRQ73S21P)o+;)*Z zIKaxl$x~r%>eCr7s!n={Il6>(nkr%<q%z0h3cla|adtK26G$$Gx2R$Il^YPnhC~?s zGYZ5TxX<glhZ&?e5O;n1wEwk3i08>C+JDlnQd8p<V<61~p|OxZp^)iEVM+#su;!zC zg*4TC5Np^qj7d;?!oc;LyCC!-;v2(@up{RH!di$-UA)cu{|R~zF|BxxuDII?-Stu8 zt}*}jXq{Do26axc{2LO+XZw^<B=j8qw(C`Xf9#FS<f#{yn!L2v@-atf*{j9|u96(c zjdAc4t;9v!Zv-eHjZzg|w(`X`UE!%_d~mw&jvyf7Ld4*AozH=SA%7QS!L;}PIH)@b z#U3K~^RF6h%q{~C&JSo4|1!{?=0o@4(-g}encls$WLqS~eM$|Rom0UuJEDSRbAjcO z(fN*jy;dk?Q`q8YCBHWzWM(3)3Gy?d`unm$K`lnP1x{2yZG{o&vz<{C8qKzljGSFQ zaRnkHj<kf7nIFNNy;#x2G;_Aca|Hh)%%Y;EQ5clcv4Pervlb#+drw6fDw4WrYhoL@ zMd4WADA8u<Kmgqv7j|B68RB6^;Z|9|GpLogVh{Twcsr<E*=9;RI-kfPSCA5Si+xd$ zGzP~CZ%pY*yrLq3G<edr9)5B+D-}gkjTMVrS@Smr-T;Dw(6|BYYu)B;LVgvGKv9w0 zgdab!aLrHY=mRM54Fc@YhPJkUWms!=EI3N4_><KBap>C5f_~sRW?ajmHGYERAHc=8 zZa275xgbFNAHl^T?@@5Q#_O!}I|8^YQ=f*@J#b95Ii|7mVrdc|RVulx^c)(W+Te^p z4fBiqElZ}tpdi!}%dUvr(nK&QTRZ3_<PA5c*5E?;Iwb6GGoO}KoB@wsYe?|6_Yr&c zHolq8`k#fVr>@-Xd(UGpb_WkrJfV;swh`o$Pp_pN2I5UNI^R`B)HT@R@#Orc=rO4S zczP3f_`&qtBiONb<LABDBYa%!qvv>}LSM^6(vQQ_4c5QaBU`;o$8r%L&G>gNMY5t@ zh~g_bbdQ>Ya@Hj|q)srogtyH}<yFe!Yik#q-ga^NWOR#CI+l)O>2CfsU^EBYC6gWm zoe}OMrlmf%^FO*H=zxvcTzfTWUnD_>Eo^{BP02hm7Oe700u@6o)LWl252L}###Q!A z!Nx3ppg09O0}B#ZAl?eoUN|Vn&PAPS-Ah&bTtFMOfqr~7YWfynFKZZy(bmyK5Rq(F zRFT5;scF|o^GCLF&ALqWlZH8A4f3}=D-17wRNbuV(2t1+y<N1-?tCN3q!V3GwEtT5 zgnJsB5Ip!s;_KS*so}f?%=rz;NTMj_?S{1*2PF2l+0Ia+2VZoIY6$v%@mK^DAG=ND zPz8;L=u<MU%>YxdA4xMSU}Wmsig-lAWbAY1^}ZeuF_B<X1x@}@AY?>a;dj*x#kbJ~ z;7s8sG%X4DC=1~=5$m)$F?#KuRA1Z&!yM=7$Q8%B&53mC_-*Wy<0<gj-ulB}N$#=o zE#7Ha0531QK@Qjq8;1vHoY-c+d2!|!{c_+N{-emCgdr3e^di8cK#p*=5fe^1{DHlS z!b`-x<0j!YYOAy{wOq2`75!P4Y}&#jqti%SV~TASIZFHv;?WZ{qnf6$h{b(+;z5e& zPB(atr#l(mU}bSZ`Ib-HyPwi`hqW@j`Yke{flnsssCDGQWZX|aiM~ovndPgL4U<9< z1FHcq#N&e*-?A}v;bDo_cb8dhG_f0?lwJ~Wg4kL=1}S^XKmN*{P!w@fkvZ@KnAk@? z*o;*7qhyc}X4o)WJ#g<oPzMgf-nKAo!+?GwV;XCBG%chTGT@Crp$&Aq*Nw`EFU3h6 zBo%IjI+Fp8NY~{RfibzNcZ6#HDnWQI+0MWdmceQ#AJVwK1qj<U%G1%mK)$Mw_AtZz zI;IB$3CHurMdi{^=!Se1LBfP{*DwqGSztl#Q<AQXkeTzxfN&H>o|Tan_6i~!s$+!> z4o=A>=T@l>v>0Hu<YG7L8(MQmDyI>SfgIVBQhBuA&9-)7a+t^{xjwXxTk`@jWPP+G zntX}orS<UF!xI-Hucx{^HPp=!GTMJ@WkhG*5g(czeHzCN)t1N6RVtlUz_VX=hqI=u z#rSx23*XD67w+AL*>qpRS}6f^98rKC!-9+qo66hDE(ckNOT{D6NEmZmX*=}Jf=v(+ zr#8u&rpj$RK_8%vT_W258i>D{)>an{zfz~@_*uGeS<>)3@viOzAY2rP&h$AoBA%W5 zt8blEf`W9NS9I=&*B|0l!Ui+?40kq2K_THt8phTq?u_>!{p$U%?wlA2dmZRFr{T5& zVH?QE_~E@?LGiX(=q@V8#{{Nr5e;6(RAQkzO_l4<-K<yq)N5Vh@<9}2<>Z^+d1H1x zu}0#oeFV#XLH<rN6T=CwV0Q8aTwN+5({T%?!GKhuHGYn>)V-k^o@H>+eM4a?W02<S z3#*!dNUw6rz$3M>ja7_W?fb5{lZ2F&d<=XPH7}3=%(cEj$TI!iuP!fJN)3Db%Sr$> z#ItLZZL~ZZwhH+<NYI#E9gwqrPNJIJZd0|OyWPP}A!9EL`B32KHEmE<7Ng!orDmR6 zL5w|*UguSU1afrKc+!W=Io<NQ;A-oD(G}G!C&Cwod0v&YpE?#R%ZLLNxyCyiMa=>H zi`uQoTW-3*!ph;Kl?BvbsC={>D0Es+hhnJg87*>;pZxs29+o2<D)0cYOjL>7_QF}r z(hNOfBBx4@5!!02rFxAdKb_a)J5EiPa{&3LMC@wmH=P5?JuDshxRyosLD)ZiC3T|^ zk!YHvZ;cegWgW$MhO}YKbXzW@)v@aq2A5_*<!%3le#Z)7+gHEwiw1I^H(ZF`@y{^h z))#>jjO!|s4*UMmz_y<q6LY59o$oM+?>iXT+E-)&bwwW^_g5rfZ-v`8d*Wu$9kIOF zjDlt7`RbAO11^cMVn-=L;|Wf3^TOa!T;+{KgZz$HwdQDtR)X6TVWX58dbbLD<`nLp z$OO+=V<ICB!eafp_1UhkBd$a{Su2)22z_@#OCBA+^{`dQ{T3}GQJpzG)_kHgO+1yK z2SyBsS%ZGMe21^fiNnmScmGI3z}BiNSD0e?S#n;8EbP10RmNZ@m3;BBie?R*#X@w8 z9;o<AzI(mW<&r1egkL4B{o2X6A#F>_+tlwV;8YR23ygQQ=JSgd^G8TiXCw;6nrMo4 zcI^^xtHybA0Bg?g=Ss8--=Aa#jJ~dVOc%>Ks2e{)y!Cci)No-)%YCl9Bkm2IpS6TS zDYmGt*3<8TrH|IxZfa=RKV%!4E)i6fxZ4LU9R|leczCzHc$b5(6&LfseCJLtupX{U z5oN}N6zp)J+{S)Z%Lw6-M%|7e61Twk!-k75Cy5Zs?HoA*XXO}_{1(gfBxUTs{yB=o zda}7(8y5F$#F|kk6rQNE$k>NGzdTxiNjU^GRmBsXUwg#l5nx?1JC16x@Dg7G=3Q4h zTy=2_%ZwRXW;>`Dz*YV^kzzCZ9hNCNqCs7^Txic@tm?k^qG@6COiILQ;2%DRMd1cS zJ(lb93U@QmFoOg@&}~k8Gd!uX<{9z4O(gu}UpG<Mr8<LpO6#r;un6_3KQ%sPd~@AO z*ZA=rYYFv1r?sOj+gl6&A2c^&w(9zVXN(m0qi7MfEV7fCBDO1QTbDdmR6ffiHsEr8 z++q73R)EiwzcK0+tq%B2Ah0jO-LX`ac}VKzEk1lZ)u__TbCUVW*Kk`OtL;<TwxEm4 zJN;SaW|Y+}Y$k02azr2BM44lU$@e`!twY|hi;n?pJva+SfSN+Numz}+#V6V(Pn(Ut zuZy$3mnV6|EvOq?_ZpV%Dp$yFi{1j+NH6Gjoe!+*gs&7_G)rxY!gJEmUdw5SDXjM2 zP)9$j3dE2Nd40SVf><A4_;HktB{ra>Q+Dzme_a|j;0&aAva_F@;rBh7gz<`aQ*B?O z4^U+^M*u5ue->$(z3j`GD>)O#wTfwur3;8)VkJ*&qNf7ZowCY1>Dem*V8o3iQ^I-t z&uCNkSn|D{6XV(QCv~vM0~3u1640sf@5%P72cb)9oyDRp#>~snFH-1?%R)nU^J>w8 zOEU?Ogqpyt%naL380D#uPIyms<=3EgJM)*Kz42ng4j@7Hf8MW<Q5~f2@Qw>@@;4#P zyKb4@v-W;fJaW7L7a`ZAQQ5&$MQSBQtC{opf48@IdAZGJ4KJ8p&b0omu+I#fntq52 zEAg$7c+vEv!;xkAlHcEfuAPskA%JrTa>C7zBOD>kl<`8Q!mIxC>6K03@frUo6teV8 zyo+2Wv1Re<vZyzNx|wz}xr6Udx5E30sd8@?{!n?U%H1Dr5R1RWYBA~j6EzUczoVpY z>RK+<{8jRQdUN+-IV3jJAV5~SLy*@RTap2L53dD*l6lnme(^MLg{>lhp1|XNA%9mw zXcO<(sW<^z0HWhhV5T=^a^#I+>$+P=pq$A7K_~{g$4A)h<~m4~Km>dIoi5pWb(M6m zZ3l}UK!lr&xD>It%gD1>^44Dqh=D3pFHJ~j2rsMsYqXCX-YYL9TW^G|0Lk!syA+h5 zbf4Mlh%CU%w>cMh3VGBTP*NfaZ*#B}In2-C^Oml+kE|I^xy=MXsw}_zmYz^Mj}(Io zgPwLC#@Od}u2I}2)anTkm(#?5mDR`4u-m)vP*+t0kQ(Iwsh;2uiRSvhr<cQt4m=of z*CXD+HV7=BZY`+KahqeKe2ln=9hb^VpXM_F3!O2@cBHKY11H9mR%S70E&9UzPeUPi z;HNHqAhu|*<T454bU<agjD!#hWZ`7TIB@(GkM@Dg@&JqL>N)RGjE&;H2yR{iq$cEQ z2_0rk|Ans5lIzU!_<W<SF-;L7xoLq;{8#+oQ<VsV;0hn{x22UKUPBkrEkC_A@;Ag= zMcLV=!q_tf@c)y+nN&5v8(6yzQFVP0Fj6O{@u3cyZM@9uqCn^O5<)SwWk60>@iG?L zrjBV?u7dcq7^DmcNH~n>rIuG|krGEJM0P|l5)<51u70I=NuC1(UjP3ffO8&Pv3A01 z?^drjEPhduw)lMgUsuQe*(_`(2N*oDSV>=r*|Wy5a6;e<R)Y$C_Loh~sRl@?S3o~L z=(HL}21B&`M@JcfR!6?&c^Eo3l9#U%NUBX=@`wM2*OP|O**Jp8S}Ja)sMFcu-J2#V zGIYmJVySU>;g?)t=w_^@1KvlNZE26wZ02EStfy)Av%Cl~1j7sDoZi%$7v(=?4G^ci zkv$+xBCjVQ1|p$-MnA)#(f<~Fcy6Vq)B34I)}2zp`@4R;CR~Ln`FFrqD<9|a2OBwg z4`LFX>u3x^h!KVO@V&q?3ocKpn5>uoyhmNqkXb?t6a|S&HIZ#^pVwQ^UyU5Il@!|q z3KAo!hY(o%rxt{J5oelx*!6Ili&o^EfEVQC*Jq<Ei4F_6#+|^b&ByJGq@H#dHZ(5= z4wQ2i?00DjL4}v{aY@6*yZ-y2|HHbuTx!mA#0oFgYU<-2Uo`^!86Hm$%Vk!yqC+~% z5oSdVQ$ghzI1?n&fYhim;CESQ>7!pIz%s*?7KF}wf3-F^7v(XDWfk<VC=rlCiUF67 zW1-9!e==92_3!#F<03xWLi!L<!Kq~a*5keIE)$aEVY+Jz?tV)zD>*`FdGBN6e}*Yj z9=6|B6gI~)NW^U)^maX+_pga5$A=`dqLv_1q33Bs!oX%+CnqI|u;R?E&nVOrP8yY? z4ZeH{C?yv}>0zrIouM39eS-#Ha+NV{1T9Jpq;8Vno77^DRu<hju|b+)i5C(6*V~-l zzF{`ebBovZ{Brt?4;~ZX6aIBf25|ikue{jw>jC+Vh|zf>+&43>E-4COp=X3`qX&+V zQ_dY_)A^>gkWHGv2xY@NNy*`__OB^F7CYy0a#-HU0?7XKi4Z>#IyGPo+I94h+*Fgt z^33W(zO7lkvepA1uL31-Rf{FU;sNGo^b70%+@wWYxCz;Y;p~{3LcRp!Un;~-C*Pb? z3y)5MFAG<kUElec4l72&2S)V@*ze)m7AW2;41uRa*hox8p1G#J{KE}FGZ1e5I724q z9L@=1hEkRhJ9kRlWZ1y?=-PiWzt9Ibwd+udk$Q@u{OJu2o;v&$SGZD3rwY<A_#QmQ zvt32%WL8D|)AxZ4+`JM;xDTbQO!9M7m*&$utv^ZHo$-yHL7>;45x*DY;ZCR^IQ%(i z4Kd+OINXXN?Y7iFbkxqLjX}(#E8!fHEf^7S2nXtFY~}kc=Bfh@-kp#4hwKI6XC^tj z2HEjBBdM3#i%X7ofh!KK@MXw78GnjOVWYRN(DYJ(n3<fCfkA6=b3m~osctWO&i+XK z*4A9@tW<~r_a3cly&Gl_M>N)Dn7bVW;Ebv(XcQ8jNe>=}z<bS7`P(FS!T;GmRl|2o z1y(DmSIQuDC1vzs3+|&NGs+~*m*E4ZSn3&GSbro)=5)?$9$_eYF%oT`$edd=8f;pV z4I$2P`BPy}V#}2^GFGW^@t`u0T5TJg7CPvb>CIdXdC%_Us?GtS6*+e0a`LaR_l*|R z)s)*k#U`9BAapH8ShvBOAiyt$yQ}sBzvc*BeOcW0v^h8ART4f+47;uQX0tD1X1DJ- z`wlicYy2-EYEX^u(`GJ|1m7!l5BD_uzHK4S>>9D$T5Psa(>J|X0D4Z(dezq(1=GfZ z6{VMWQu$zAgltzJ4#mV90lU95C~8xXytT#S+6SbJj;6DIA=_7h4Vi(ah2#*mR+;qm zy7l0k2<hb?fEIwX(nVSy>ech@!sE@HYj_v%9<H)WOINUe$$lqIW?3gZL^F;1#Deob z0@mh);Cm9LEw<uGh*EHlZcv5VcDJ{CtMJ%RK&_FJ^oZ$EA33K%wVg&H@s!|u3**Vt zHVVEzOi0A5>SArAiPcP#Oeb7l6S7BReCq4PpgRv6v7QoN>PDei{_E>r3tWy;f#k>) zx2I5pSmiMoUgJjZUSifW7Sb#5+cI*a&eo5%NoUd>{cAG6()0X=l?|=cV?|S@fq}?! zKn}m)cr~e2$Xmxvwq{v8o8~wNCLj5tjn-qiHdC;W*%$6gbkP=JjZ?yvoAJ%k6BW(U zyS^FU+lI}=Fs^!YQhErLSC~0H>dMH)QvT|rKp04eGA>XlYz656Eb|;Os|I(BHlO;+ zr^g59-~33t?=kX2b+YQE@H5t%%TOq(&;0y^r`M##Auj)I%^QVl>}U${?FYSeHM4Zu z7@MP1AD%|%Ob_C{Zp60YcJnOl6F$*u-er#&#q6QZm7Z;bqEeL+x6lLcqSkV&YR(+Y z!j%-zmXj{@{Y6UQ85=RsBJGaH9#h~=xi5!%f&-kIDSiKKmV!5BJ9@~_tBfw|b`6I% zg<#V7uX%Cd@y3=ijMim!ic`-jBvaxdmBPGJqzXCp^`#-=p-P@<Yd3$Hb$k`$A;aH! zK2Gc|9<ZSa3x?@KVX;nMw(pHnMb;DighniYTx%jso~jd>ink4YQNanS&#{ZFKzuZZ z-nQ_cIk_jN)b+D+XKg322u}Otmuq<fuv8CEG??68YdOXYUtENLAQ;;Qq(t@(rlCNE zCBuqtQ=ZYV3z@$5z==8)P&CQM1W)kN1c>Nm>i2mvh}PU0BuYPi!1>Q}CA!^vIvjqt zP6~-_S&73QSA(RFsvB+YPiD;jHi~gS3^Plwp}w-|bg(ql9)RU`J6SRFHA&pkHIJ_` z*v@~MrZ(V>J^&wI{1l<3%ktDJU)E@^GE}^g_GB{H&}E;qm|nS(D#I~OK-iC_98c22 z7Fa7CDn`i=9uI(e$RTr{VuLH9-f4^<a=fCCq6Vuo>{yY!Q<suW-3NRG4EC!PRv91_ zDv@9Uo)o{V+;L18JFF-LY&(MDwRc<QK_OuqY38!xJ-ghPHnh1Uqm6ruUdzlYOW|fc zk8if}aMPwnBnt5>mO(khVYsiXh8@X0YQiz{vlZbM6TVWX)mG+>P#ov}VjHlDIW0KI zR*3O;3eZwI$D91d!Yp@cyBNFr{?KYgkq$J|A*-G`hy!F-Uvan+o?mcP`y>2;1JD<& zt&ZgWcdtdQY=-h<u@FrHMLARi(q#Y*%*Q!Nz*l|~VpF)o#7qu~K&vWGM!-aNsI!OC zLRpz$VeuGjaE?p{`eo&Wq<+OP67r>eRTDY}QRNxV&6KM8QKBy9NeZWme-4#TgfWZq z=?Mx~81~3-3~F}TiIM&oEnR>kdRJ>{9h!7oX@~;J2vM+9ebd<~mwsbGr0uM>2MGPz z{<BzvgddX4h-)7kwN#&%dU(_+z0R82rLt1D`A7g-=M14=<fAU;LhL?ptFh!LqG>PL z-vfx+T|BrmEx)35t&dl)Vu8Ip2gi}^k4EyEK`3|?q!5aF-@|v-i2EiByV$(*t1#Jz zxR*eA)p*k3?ElN+xnpz92Lz>xN4E%U4m`YnYIDZxKurh!C7Cc%Hv=uONXOdXAKq{j z2m5t0fa>{Wp4VZXJ2lk`W)#aqMm9308g?+bhL$(_p1ZDJRTL55Mhd9ujTSi1QhDT< zE@q3)=G!2vc)Jm;LPdsIukjZL#YC_!=PM}h=rzTQ8<cOz&Gnm`DSm?l445&R{W8|K zkkLPUH1WF(;Y?+NLk6j9ND)q0E0O9d11|Y^#eFiecurz3aZQn9&k9!2VcBopQZ}QC zSk4ijzSC{~yl7&U^XSmcRJZ&rFCg%tq$sa5bEBc>ye<7dB+nrcg5+J4*)UHAo>(c$ z$CMy&%Vo?{wXffHfPr#GIgYwKQUQ(-*6swRnQ`YQo}yYX4HtxqvubntIpH}r7vQv+ z6s>q+q=ET+|BMW-?REOP^&gD)rrLUzGcz+eYS46a@{d5A8E~vtQ>(~aTI3W9FshKj z3DlZNDyLCiDZ;V>Zl-FxmWV3O`uo4l6@}~K>&@H-+_?I$HT*B`-YP1tCJfgM5G1%m zaF^ij?jGDdXmD@b-95OwyF>8c!QI{68tBvc&zUo`)>&(A=5Fq)S8b_XRl9e|^S$qt zHjm%;xyY?G+rPDE8Jj|;4{O;xoU6-*`Z?GPBiZjaW!xX#B_&UW^Q{Ln06yEN-g|)6 zT!r*Y`=V7}Vh=2`b$4|wnBMy^SRO7xnQxk^D{9RDU6>)+t+nd1KqU}i+au!VXLLT5 zy7yLDPy)RQFm{~lshwx1yXrkYCb)<`SQjX_a*oNMc-;ScG|zLQ?dV%iKezQWgH!4c z;9^SM5Q}{>W&GH*lRwpU4yL|K?8w%J*K>3Je#OF7;i`+j@SuC=XU1l|j{Vv6N|x@2 zZ;e%u+vQAH{@iS)TXs3d7IjY}n6?W@JL0Mac4sUlYV2<x^KWbd6XyW(3Z3TVC%anO zt||&GmV%NG`3o<~MK_eDzJK3*??`4>^niOc0MO{uKN{rKx?R$8YiHMW=FdYVpc8Ct zIX9?jo3?j0ccM_(wB?X>xcb;yQY^>Bj<mJrG+VQ&JLj@A+smF(xpcwP_8>Z^KW$){ z@w2zuHa+7o60q<6dTl&+T@{!4t(LRmiLi}I@Xl|r3nWD!W!BRB(QMWB_IBFK=~G0N zU`mgsNxz_+Wp(wA-2P9Rl&tg$Eo6E0(7OZGf2Gk(qFMHb)q;l2FE@M9SegBE3tQom zswtDn?VuH=Qj&F%?7=DD8U~KFC2J(%E{s-k_tdzHYQZ>PI6b^D)Q5&~jz^5~E{MG= z<yvr;-#eO|l}($VR%%@j#iU0H>}PW``b&~Y8S)=cm-+(?)U9G!^DY=kK4)k$uU&RB zlfY+cjH|SOqpntl^<$8~#>`*bz%?0Y{z3Jp#rUB^E48BSlNf`La@=^2R1^iUNozpQ zoI7~G`&0$s_!8ju6chv2jWRDNteKiW0t>oXg`HwgirNA9EzoEr$KhqyY7>7LS1cWJ zAbzcR(lHw1ChIHCfwQ|$k3Vr&EwbHE8^{wcnnInEhhBEqQNWaY{gqnwhQ>W;*NfkU z%H4F(%I9jsy<vE9T+?K^8Wf#HXEHKK>g<(u@sW1<HHHHpquEEJ#iw+j^Xul9>egn* z*G4UhBwZicv5q{<hI|nJeoI9rLkqwO5Bm?F64-Qjz{&aoKVZd4hzonq|9vBF*y((Y zdg`x<kHuP6VRo5N%u};2gzt6hybvcAnVfGJH&`V^DX7%!7kH9HR6=aJ`J`LC(vy1n z_2GG9MTGtT0nMGpV9c4t>8cE{BxkGc*)m_~1TmZ<=T(jSnmoY|B0r#m`!YBPXfMr9 ztm1&rzTzXDRf!`pSv|yDg4E1{$66jN4v-U-9KqIXI$!^@jD`l)YFK2<t}8Gx+v~fz zDi-ahFVi{|?aAb3r;tAg$|SS7VbuwjgWJmKI(uvvmtA-Dti9gwArs@P7QC1wS7dAx z&loe688upq^AEY6_lmD<zyez6Lc&^k5Y7k8qfk#93&BF_Z(KQAPdGLm+j;g(+DvaC zASA#X<;`;?s48*x%lePVr680tmJu+)L_Sdr%}s;s3HD8|4*a}TTF?}wtuLZn8MOjD zVD-Nh?Y}qj2^28>BnngRNSFPd<@`XyLspxyyZ_iU2XD$1$AYIyP(2n;>gjLloT<tI zhyE*P1;aMzlfEB6XF-hrB3hiZ{MWtbU7PUe;U7G^)&gQUe>`_7VVx2ZI?!+C$Whs? zDX7d^u-eO7U>~j3v&TlY742JruoaAbRoM(f5HIb=C+X`Qtfg>oq2%Ig(FZk}GI;3G zs0kmFe41nj!be0lv+Yf`lG^2OS;Xd`!o7RoGTe*L(s#GjhM4Yat@!nv1L>sJyN6eD zWS7TfhlbwOIR&e~dW?`}H(P9W9WB!Yx8NWdrxd1?f+F?V^RR1bLR%D}H}AGL!#G~e zQ{&bFA*y~Em?;$14`s<wvg?M^8D6kxsO?7(@S?&an_e<U`f9UrP0R2n*+q*in#E8( z6$k}v=)O^J-c$2Lcp}iJ>__H4U|FtWOuc_{a^0+*;|uqt#YVFpDI2B+`(e3NcR>W_ z*J<;j>&iyofBSUm9ck*h2H_)M5dfA;tAt<O%Z62%l$v`%QtDWO<z%-1iB->A3U3$K zWF>E~gL#*Id(GnwB7;%Mx4{FN`U>g;0edJFsWQ_c7erm`5t91|IC-5c+Np>_G?Q|2 zM&I!@Wo>cTkYH%Os;5gKdBf6<amJ>Y{}YZ=Nyzscy+hUm%O`E=CuBae9Da<0`Zajy zeLfSv55wjPJ(2UTJTrVer1b6%>7c!F0rA3Gd`cD&;<ACC61#9!++bQWZc+X!TTj$K zZn|$^?O(+EghiR!Safar4|s-8&C5A6U5Lj<V`W4nRk?9I3>2n1C&}>w+gskg5|64- z)*A6I+HL&F+!kRP*)Rr_C7p-pRH8dBkd)P<-YhD$G~%ryTN2{#7rIv-gqwXmJ-hiO z=w`Y<BqM-J;d`TFv!Wl2QiFSK`Td9U`_C{Kq=4SSsFz|L2AVtX!J48Lfr@)PAU5}U zXamb;Dzcp<VtS~;S7j5!NLM|2VjJ{;wkClxr}i5g@FcC+r4zjGZQ8Xsux<9rV$JYR z#0wqA=_MH~)d0!tQBepJna$6cby551qN?+D-q7RhC)ie98tU;|^Gxglucl=+%;4J1 zV<vJ&9D#nwqAIXt>Xz`BKakbq_(9{0QCFfebz&d@lE9{h+@}1BfmM}_H}O}4I&~~Z zOdQ<#J<AY%sz@!+<}H6gS<6eY7T?bMa~$uAM#KE;aQM9ytphID1t?p_Szq?Y%q;TW z^PxwAaZA=TA{mGvY@%R5i%nJm-QtUqoSGL8&RN3)$s+RsR#!VaZqBMXdmmWfvwiJ> zkL@;g@N}vAlHLpKw07ip?!yBA0X1(AxDRsQhd&p%fj8G(J;04=TS}SG<jcCCljD7> z%73SpB3QlA<bR{%I8Tg`#Jkyr8E;~`3FUs#`(Ip~<FkW5z6;;$^LpI7Gca%3eT&rR z$>Lcp^Mmjs8N^bOV>^2q(#u=0p+U9(8OqU2;+8cU(RvDfEq?9*sK5J<h~>=x7s-qc zQCzq~1kh*??SkS=XfugNO5@814=KeAZ?dhMMjGwX4}Vx%k*q+|i_9Rg6#jV7D<bHI zyjphk0P4TwVT}igERwpK;16-`KCS5lc3#<$hua6a7Rrr?F<+|Rb@a1&LMi5e4N@Z8 zxbaSvQ@hcV0!7h|j_W-XT{&&NNC$U#n-Ce0<e>j~)u`{v|K_ELz75po_)hRPuhW@> z9~?`Be{o)mKTBz)Y~f-hhCefM0g>YjlgYRaj!6QSSuL7>9D|^icp!ibys*Vi)t2$= z_FnDxW6Gg5<<q0)$k7AL+C;|N2f6inWVxPwo=te{Oa;Kl4|iL@7~1KnH!O<7^Uve2 zjY?);lJBmP*|2Ytm9TGc7K%SNK4kaErCJ5;LM2TaR_|S<#%wESt<?w2ZTr@417vSo z2Vd@=HMAd;etf52m>CX!NWTEhzezdzR1y#kY5=5+;?Z({)(%}yv*tbZ)oSV<0x)x@ zUm_mcGfj^5UkO_}?DMu%UkFaZ?$MtsQw+DME0$6ZjW;x(lf38du|h59J_5y7*MGzX zw55Qa4*g7wci#@JY5r&QW=e+s%BsvDpK%ymStKC}G+h%$06>%RHdD^(^97{In&*1z z%FV_5l<yQR`DJP`2F}z;^@10BbCn^Ih|MZ*Q7g+}ht9KW^>08eO`7$CN;Ro%vRcPE z3U`}sZCWR-E#BLMNv?T`60go@hO)e>L%lOjxJd#5=(#fY7c(N(jh&XCUk9B|a~-mO zBkX+H-PIzsXQ1xi+JhfcIU<{E!QmR=O=$u4mATriqwGxc>V%~lD}z0j849=9i+Yr+ z1irHP1bXyx;y8}0ak*^x*nnT}^Fn*(WbKYn=Q1LWqXWOn*>StYYxPQavPtWyv+<8R zDI2!B9MvPMX@|NdduFVCYjxO>>0gJ>Q<>yGP^bmjLSxDW9S!Wy6^Ym6wdAEdh5&^h zHA{Kt)Si-Uml#-YT$rXC_Tqt0*J8K))C*M|!K2Jt8lc*TR}6-=*`?*gdbjyCX)!1} z$*)zCg4c@X;h(SSe^0t&$s4wPFD@(`b03(kJbkW@J0lm6J^Scyrnbhr6n1dmO6l3- zJVv?cLV}8J-4V1Hh->=QL^H=anPT(y1U9wcYuE>hpP(_c(u3T!W!g&6d3bIupZfPp zSHoXn<Oc{=@(Sy5fw5YOz6NkF#r#2wWLFH-I0KC#qn&xfnXZq{wqJywabJ3I`8;n` zN7;Qn&eL`cP0?ftHjIv=UquNVRC2pc-P?7_Q@t~?E-sE0Q3K|Ix1uLy-xN(bVpC6B zTls#BI&>4ge?YFu8#IDpGtIK$YQ!&#YitBG7q5~Ell#>N6gE0kXTS7B{``4l#miP$ zOLc=-Fmbgbd4GHmIUio|q*X32w)5s9#@|TB78tl!(NVp$I|71KSZ??2aM1!-7^Uj; zEBA%#_o8LQNS)vZ{o>$)Kc6IJXy@#Z1lB{P)o%Cc?uzeNlTVtHvGHicIiOsA|Hb-G zE6dc{v8v>KKw4g>O}ujr1Eff?$T-_r`F|j7gkLmV^E-2hMf>MB>O%F3x;Lk?skLYA z%S%XS+unO>J$|;1`MZIAfPV;dYB0Tk_a@0Izlr7u#<9b?z!F|usdnb;n-_<5t@esh zcc$x=xC?xl=AO8k@x7v|#<Q-Vwsr%EO>$<v6Yr0M;_j7uUsT^-DGj~%ZM0s+-v49> zy_3o|S#5f#00~x1Nj9^`5Sn0wucLmJ-Y@vy{PiSmZFp!s5I+LNIqLk;&|h?_YC-Am zp^=<@lb`1)TU%V2Zl?6Ufq#ygR;&88_R5D}n@>i*_9$a%XWF;V<H#KOiOpgKeV@nU zyWBvz&7cMMiQIDj|Kip>>yRYISyUIfaBzV8fEw&tsGgt)Kqj%cG0O~W+@E(9hCuVP zv*P6*Sk*)KF2$DpuOY#-yQ1{0fJ*Er;YoAnbmb%-SQ%uy%yA>LkE)N=AwI_wqWKkj z$@b|+Y?5lVZjCOV`>{0+lZ|sB6JGW6y1%9a>OL8@n!vw$;BWL*w0Jd|!BED_Xgmr_ z1358&QsVk7QwQRz903Q-yKIUy%DpwRTj$gAvA7QAi7WyXQ<h{%W$`0aiE+J+8ub&% z8|Xsr?TA=;G~QDWB!65%PNv{fPGiGBc?l)^tD--sE^#8gPWzbTS<bR#GM;rng9e=9 z+gVBNDXu=Ab|@SCt<UFpog6))XHx|BJvB(o(H3aNc5X%<A8PTaMm<q|GkOMcs9_O` zZS-;fxH1g+!=^zdpwcqe78qIJ#Qs0IHQlE-XADaphf3E<**MW-)&wFZy?{Ryp`PzM z#tb7jdvNvqtOk6K&dTacN7WKCukwTEU4JLcd0Ob#gR`JUGJ0EWwx|ZfBuEv^nBQ{^ zf3DSei}NRjofaNKCbY{iEPCoBj2o(U5V1JV7oHD2<_b_3@K~n(T3je!85PQVnjl+h z{&A!e?Ir4mSJBdIpcBxCeEDQ|lVDS31(qH=^H9pl$`Vv=O!5US8pa!Ly+Xhk8h&81 zZ9U@|M#Zz3?J9NNb43Jra9IPk#kQl5-Q>y;6Xsa7`O0-&TRE7Cew9P)nixc7Sx8zd z70b!$M^L;Jb!=18;5R~kiS-mZIX_w@>$#iMJb=~&DPBYbjBAjYY4Zn$#)!+8AiP_; zrlD2VaY=k8r$W<<L9#UPYp>c1guD;SZ(A4sejO!sIzu)HJ6_7nC?$L9bnzv302{mD zw^-JMp@Q>zV>rfUVSm&8_f|8i!2KtNXf%i{ZwoLgW`?RB6CH8dI>-u+)Dhq1`z?JT zT({Nlf4%T^HKaOUO)nVIOeVXBK@<v#*{%_ye4Kzw9$DT;tg7{SJs<@R3#eu2E<lKs z1mxfNJ)jpz-n{m~UH5sQgz>L0wKA5bkI$=m_usv;U*Ty$a`jYP7!t`%a-t5%KQ+nn z;E_dCAM4!$4K99Vy;-Pyuf{mDtoO85f>mWR@{#;<DF+Q<grmlp09gJEt^#Q4blR1A zO1uHEarwp|7|Vh&D3tJ34iAfbQP<l%-?d}_Ex~Rv{JoY#1M6hi8Z<Ia?FqvmtXM4~ zM}A_=rBk347u1{dkXW<5Jyn35(x#}G6IS_i-&Yyvyd#f@5G@*tcq&;X{K!f@B7f~t zP0?W^M>Vz`vMiI$-Lj9t!FCUsTyfv-N!7m{wEPbY-&A=5K=+$z77>}eE{bw=;~j0S z`md1lF4+|h{8-&WThg1=*Q_JD!4N~c55~=zCnkE-b`G8M|8s|t>1A!jU5A~NlYA#h zYCuq$l(c7Gw>ro5Tt|aZiNj?1vDvmSpKK{`JW8azIhc9#njMO5AiZ2)&BI+gu3PZX zM3&~a&bCrEgRCpSP*ZRBxL_%&z3EB8u;^u;aE1p898-%lHG3PkcNJOf=4rB~8Rlcw ztHmHgPO$&}k?r~gu*7W0X?obJFS_;5=xGZS7y@$qqEz*aDx^K<?|o-W1_dBCxHev1 zUTBl(j4Fmeg=99XLMSF8Dnz3LwqfBEzlkwW7WdrP?@rXHr&r}1r{%W7!V29Cp2rMv zCt&Z~bLv?LEn)AayK*ZxA(g8_Zqq{MHv|fdt{GAW2GJDtq`KU_qFsFk<6YM8LoK~! zwY_?al{o_m*NGnXla?H%bo?xWK0=RFuuvB832B;T4*}<VvY$gF!V&~af^gJ&Db6?W zN(Bh#T|~VNU$`oe8}%*;J?Z@RxXO~Qu+$?i7+JCZ1HIM`aKX`>(*LQQ*~U}4n&@iv zJPl?}v6(e21#DcMjPKDh`a1yz-6n*bv7TUt$h)_@Qw3xGZvf2y#iss|kNNa~_9^yP zSg^7nvq7zR#5yrx<U94F)Oi$H^(8ir2aa3`Z)Qu3Dd+Znf~F4B0E#y=j~RaKRb=ZJ zGm1!+&G&DMox|4MKL6>c8QV0h9c{SVxKJ@fZhyN_D3Xl)RGP0-<<25_&D>%*R_vMW z0W9_ier`GkB?{qh6VtX15Z7__&~=#Kih4xb2wMq{-jBwn)SyI;Y!+yu^3`c<<w~S5 zZ(;cVVO6-Wp;LH?xT}Wmks35rw76{xWO>CRNc}4ID?*DZu=_u9OsBF_Btz1%D;I0r zgM6Wo_YZCt{K)tdnSK_Ock>iPvX?h1dMCVd71VP6?ptyxu^~20E?m*&YMep>m*>?U zT66@~xY5awI4jsk5i`Lm@x;o?KZx-YGys_{<*2|)qq`bzF}GPM>UJHSHdYGw5MvnD zIv(dfz7an4I)n(8n?CuSYE5H+l4o*OxV$=4Ejv)M8Dxm^(C71v+*`}K7ZYiJJu<v@ z^J6=%4m1>Yb7(0yWPd8#`ls~ue+!*;lw+-hgBM<;Z}t7Xd$G6;j0lT1Okx>F#O@FR zmTlY87ZVWSU30Hwbj~GRwOQa4YKNaEQ%18KOeqVIN;!=$-{jS_?9jjyyrcJT?$zz^ zs@(>*f4GWq!!XX}d?Jp4fnbTSAB7d7S2YwrmQgQ+{#JuGVQ;O5t8?7ed4|zsmc1I# z!whu;K5N7Oe3SgV`M@xs={~?l0{Mk@EuJSzg!}K)S13m^>%UsDU3%JKYbZOv1)ek* zl+zM7mh=M$N(tRF!XSE#Z=^R~sT3pg^sdNtk*K2_|AiMR;391itsn8CZFqwLr5+2g z8$F+I(c6Rd{)Ay{77SXvxKNbVB4^=M5O^R}eAIuA7R@oeIU(2;5w2rOqImCP+QP5W zQw$sb47SYS*Lz%ag2v4V=Q50TSeK4G##T<lsC|80>>RsOGO$`xAVO2-GBQ;lOWPnr z+OJvK-F{S9?y4nFulSw5m_9K=ta@18w_EPZ?6z<L=#W{~x|3Wm8zEt@#$$dpzOCgn zdUsi=bsw2u0$~;A5R@AHt==EJLKzr86M3ircDugzve2DjJe)2vyFSO&vF-RiMACy5 z;Ly-qA)#(`asK15)>**rlK)eVjradb2>*YuB@~<q3qRJle-eU<p<<aW>!q6Y2p3Y? zh6O8QiSH|dRq4n&7A!@c%~<+Lvd$yeN#{c4$;J2G{=r~&96B=G%J}J$;htblOkBK` zAT?Ok>)%hv|6Ruam!fT+5sD?&5)<9($D(r#ab&*}w5#fCL@!(T;-;zBmaLa~{*V}V zK@F;svqo<oZy-*L1#j`RC&xJ6ddLYrf?C~~9F*06g8KX-xn%<ZPV!0x*kx!kgEyjG zB>B70EL~WUgejgZ-%=RyQd)a)_!HF<_2D)#PBU?MH>FiDq0tNr)F@J<L&Wpd@}l$O zWsE<5UUZwMe>MNqE;s#jw=$8#0c?1*^?1x^Uc~+qj4BETy&H^ryHw05@t7k3hX^;s zymZ9Ur;Nymz-;66SyYHGXx)kB!Z7`H?CW4x^P&+k5>YcYY3@N@Tg#NxSPdB?KP1uW zOBQw?`7r{8K|3W?naqP2UVmU}{~w9Y8YAv{Q?!<&Z)zrZP^aic-Ys7sk_-ooN>3jU z5yB<qJ<HR}df>rdel{4yM`6nfouX#{%q5nC;;3tx3c(d*NyFfUipo)(tI0}HD{}~< zUw+WA60%6@2hW$55Z<W={gKsDcm|V07`b{wTovC~5^|C>D@rR(;rM9}Ns9t#P^p8P zd=3E8(b~}w)58VA6bZvLQim1^xSZ!4@_HHm$yc)ZEhpd*akOjaGbl49xia4gk@e05 zTsC@KQw@tnB8L{!6&5)b4^fK#o(VC>U(!G3m+nwOcArBh`NQ>8frl!1kltxzE^^55 zO?T?4g(UAJfz-id`(-zTinQoko=A#wob{hFpf@_WpRv_&oKYKHXxF!RRmpLgz&iPm zTMA;Y5^jjiFGgpyAD8&pGrcfz%{(Pg&n^2SLJ5(`xHs`B(%(s=^ug;8bj-p<=`NLs zHz4OPJ|Cr!FI2l$)o(tUH-k7>+&Y^OO1$5gm;R!oxX*8QHuesjU3iOQ<4vxYLtVC( z`^38j-)#-ikRpi(aFZ5Y&<TcyUw{6wWd%W8UVi&+H!#iQwA14IdO6D5QdM8X1WgtX zX6yjV9qQLc7;5D1u)ESi2ktQ(gQqRg%h)*P346NP2gtv@kp;xH4ZW##ey3l>hZ}s7 z@M3E>_ka=~1S^Il*L!rkG2a2uXiT=Eo?q}=k7IAfHAom91PFYmp<1xL162l@q9wY1 ze{_WeBAkD=nCqO#30Y?9U+GvhT5C|Q(;QVT>xmx3hmDb&W5_4ii=wf5eJTQg_sK~Y z2cRAl!aqcaYIO}KHWNbL?yTURFzIX|UefIH18u|Zg2;9b6@I)ydI&BnP~f&dz{Xzo zBBn_!F|#$M!s(6AqUSRS`QN%<)PW9spPvsPM!la%e|R=#tEoq{wqWmcq^s@PM9H0< zPojX-^7t~VfZ;@N`NCQ3=>NSdY09z5#b;<4!;n3&QlyWgc)?01u*K!+<AKn*M5?Hn zgC#dc#v{c)KJ(j`+_wsJ`hD(4u^HU)iwW9t`1mQJ#2sr2Gy~GNh0DOtIwAU&D-&;q zp-9+Vws=DqnBNE4PG8m$bKw|PV>qjuo9y{{6d5S&oJVcYr*9JS!W+a2taQBg*$&gY ziLt}4iY2G#kPrW8ao!w`7^TH!QrObZ7&&VPEWfv8rxyfInzrS%9C}0Wm3z7mo34h7 zC&%*%&1h2`(~0e8<nAP0Q~Q>k`#bh%Tw~;>v-On{Yj9i3tu@nM*X44&y&NA1B~TVG z!0Li<uxKtUBar4ksAl1;xZww5x-f18*9D~Hkm{f5{FLBGFGOyp;?SNc5&FGi;~`~g ziFSilweABzQc?BC#+*6t(1Bd77kM@1fNoZlk9YbZK7l7bW5_LPy+^bCNM(bD>^31) zqGpGHUKA$2YIC+JDBpr6Uap&DgHKx+jcE!2QRSwr-f+WF%2}P(S^{$P<LM3VN-V>W zZ;B>G3M!;$76V|zKffAwdQvX)1vDi=$6B?D?h&Z~MzWV!S4?$zOhSiRevQ&d5D?2A zt8v?Rzx$d?)ktYHJ5N||nvD$<5m#8C{EPwAFakf%^ju~v-jIbmsZ9-2X#4f%x94rd z(vztAgQAx$pM|ufB0v_w5I<uN9GqN5<EFXT5!+B+X*j<2a)YJ$gHza~_~;`2oh#Zx zh%_QXaF|;rEK1nOx_i8bcCSc0-VMU@(LnvW8dQ2xB}@7=@SL&kN<{473*3J0<g&&c z8+ptsa_UGR)D?-*x&y$I6Ojlfybdbl9D^--X@{Et1IJeE5b379evI{poqlx0<*IA= z9eE|%1Ee^S%TX35imN)2*$6|((&XYn2ofWa&8AinE<tC88qY1DX3frRBCP%*oX-n3 zrmv|xCfZjD*~MuyAdHhZDf%p`(KHD!D*l8Bmw(wIo29&&fVf1`;6?Dsc*NBLSxvzJ z(#9M4SI@_s=4fu_6{*yf=O0v==JJW(!*B)}*3i8v0oM(wNyV?bd<82k$f@|R?KR@d zt$^@f!}uQ(B#IRVe_`*$4pdgwkAqN+OU^Bu_=)j{y@#n7#|Khd7f<o<kssgTSbnX( z&a{4axJLN=%ou-^fX8$x5?TH;zd>&)zNurUz>=b!e0rb5x<mOu<@2>Qw+WulYG?un zp7CYv^yF~$Denpt2w9f}Uhj9g{ot`s*0x3=NsG|>2k9^p<g<?2CN}wmm~6M}FHLWS zP9%XHjxJuBTDdVYU&V!U2^k@Mpr3?Sw#-&Q*yT11L+2;IIS!Am*p%M7PfwYKE=VNA z>jRZrZxO%lhS=>tg0J>@zWxjjUNr^@rFdxl9Yv*5Lh>!^K&<bF<0(e&C4H+D(%zr{ zN=LQ8<w9NLh8d2~wGUjwD9IGMyQiZ2s$_2Xs+vl6ct+;pcpK6SVt;O@%O8{NyZtIi zrCU+C%ztT$Lw4vvH1DIoGjikzsc5SmZd`lLj?d2N(!=}iiAXBQR{!RL<Dqc)azzL2 zc|&Jzatbq$t3V0pM7=KJ3N&T=UWEDLQNRZuJ3{7hj@xakVf3bD|ELoRCH0e$8hFgY zlRhRb(c#EPojTlU+(ayZF3VGF=iWh>0tol=MdZgGB<pU&S*KD60#Rr#W15qg2XL)x zhQFOCn^lE|(dmvDwD7~)pLlp7nXEOqbCh&U4`S~zLap$cm;;PXBR~IW+#YnK*9`+n zFE{vkkH1@xowEa}9ZGLaid`ADGDA!dEIjJ@pS@P=jp7fChxw$ra4aMDut(3#)1odO zo<cHJCT~H=kT3OeoUYE_L+{n;%fQ^g-5!1TyxkKjHbLDTKUHCkE~S8mTl&Nu-*1r* ztIc7Ey%#UR=*CLMFLOkhM_VHN2=`tBq&3ylo+7TC5XRGudyV_)5zd<~2Ja)hb(x>s z^tQ6#OSS72v<M4vY2~y8R~|HHMpQSMrm}|~rtM-)ZU<fBD=4o0>7K?Z=8)9J<97N; zA6Nab%{#|rnw5zahp~OzUSs+LshcUg4x|A;X-jH8U{=1#amU{HFNslxzg#uLC7oie z<)v|k;$Oo15p|_yi#WApsSU)a!rkac9T+wUYwIDN%Kd@^9;pPEq>w)~HeY*Okjyeg zAZS^4joKAZ+lxm2<;ZTZ4zQHgDOhqyV2I;N)a!1M92g1|NWe93P(DyEDm9b{@nAAt z>n`Xp{t+XYZslYwU){il>aHBkcOTS^EAeM~bb+zf-5p~~YU6KZEAEi`KAt)gmxSx} z&%r21ua=tCvT@n?4{ZwX#j&Hr#B3>qCdwxTVV@kI+&U1Qt}Jo?{>fWMODJ!gJ{?nx z$TfuO7AzIwX-HNx$~HRj$Di7BWVm0{o3-62`A_u}QusGHNcMC$>FlO+WzXG+TZG+^ zX((d}e)c%$zM-{sL{q7xw_Ha4ok(w;k?f*)a&w=1_;Q(sFAYE(PRS*`8w2LBAAlt8 z4iPr4*QS#D77r%1EaauOJJ-q8a$0naI6HrV=m5mojxrAqOF>z@_oD_XWhI97=g z4Mq8P3%j!Sn1CFSI4f_#KMQK%E{bV>ozNNGe&OPmk5-ecnmLy>+8#5^#8^i{f1j`U zJ8EXLW-sH&Qtf*Pwx-!N#S_oHCSR55-xEfP`04q{5<^t!!s_o?G9E0%MH%p#2q(%@ zE@!>P41|7oynS=xz^A?gtaFSjhO;YP;o9)m_F~7B+;5XjqV^CK?p5oKy!m911vwXq zI^Wy@ZuxC+3H3>4&+=M9hR+RJ6!7$0nYl?zOIvo4R5~Em#Z3FdqflTtoj`}|9;5A= z-ehbgnR46hujO7-O{+vdtO!ww55>u0frp9Cp0{cC!WY(`Svag4zFu~fhXs!24^vOS z_z<5&{>HYO-&OSbg;w!1pqs5ak3RFW%Vqj$x=((`IQu5hEz*O1Zf?nW_E^e&^a6PA zmYyw~>;wX-1goBV@dnBd7-#Pbxi066)hVX_BJRF8A<vw*=?Pp6#h4ab0r`51cqnJt zv7|V>47XnZT5Rr5${S61Er?b+g4eblyy8jTZoMTm_MPT;a^w|4_$;Elem)w$1?^gG zhRz4`){_Y2gBCXFFE1abW(}k-3t=2$7NM4IS&>W0sbf}HJop^;(SN7dG%$Qb<UwbW zlL)gPrUP&-3>Hc3Sp4sCg&75^XYBS}9Xieu^l2zZi&oQKg5WjUjEgl6O|6_r_&tuJ zT^y^!8lX5=^`D)%?2O~m!MAffZ9mzoMuhPL)5*}k#3T4q)S*%M-Gg18Yesf7AL5PQ zJ9A;6Eg!Kn(<MQ;;l?xRv>6;XH@CjbT<P&|yt!M)K>vif73Q)-cfg4s_Gm7^ZYB%E z>cRD5hEib(=Z?dRPD0cy!Td4`haCg?s}Dq`I=#Zy!_at!c!J4n#JCNfU^cG7_(Iq7 zLT$!Y(^>W0RYn=JpnVQig*XM;?B_CZy%`NDmeQK(vq`qk^&(SsEEP+o4mqEDdu%Ak zp^o+`WXxUK)J#qq`0=8$Tze_UJ);LJ!i|!IRKZ^b&#&DuYe5$-F=5;x&T!Z<2c|O8 zLZp;3k?xWvax6yp1Tmxap)cPN;fE8y(pP&BKjvUZ$SOVG%yws)N-r^ScV`6*j`uxF zkUE&!W5k_->rI4}>DR?s)E6;v6`%FrZh0O!WG%^`-h=7|*4M6|Y0sI3*!>wwKRW^| z?}`Or4A3%J{Ng`!K4sSDYq2NC{GcGw?#y0wUH(jB9mJFja}*Bw*hp5VGp74)_0(&! z=qawi`U=Q6@OlL1U$ZKYsQLBSHX=TuS?skV)-yF=w6H=EU(Ns@^7y|PpDlYK*o%Ky zXvgr5Mt;mO`>_iB&5Zx>jY6JzV9p<yenPr^$sy`iul**B%^7;fOE{&~+-`1A{NCuu zGu-%Ixcd5aH^wi-D%^zfP-00h4T<lH?B(MJAoA~p66^$E>Q^^5*+<?D6FVh$oz#@q z3?eK~xdtV73Z=dOUZ3DB-Br8k)uDZnp`)Gw0Q+OrKp5AHi@KfSDImv_vLm$)ZGj%X z=GRHju=QsXAs-k6s7|pLVW9~F;^39l@tz_~>)f<@f%z|w0-Xbkj+h0Dnp~ptLT1l* zGljKXVHow(eOvX^HiP1ku==PUkuB)Iv5Imr1j3UsH9^)phY+9ujaw%M`h1sr;pbjS zb-yirrQrr#<(R;w6eSOQxsuTsT2~|%L&roRu3~x=G`2J{`L}P|&#!b^`!sP&X@Lio z1~q;`MqAQ@aw`|ey(o}77Wb}pv9BtOkC*b2vJ5_{T*0>AC$F3`Pnb*ug?tcH6MVy_ z@y0s_Z%enn-_7Q7ThF8zW3<<@9d^(Z8Lw~g<pD3g*~roa+yRC5GPj1<o7?a4$zED` zv`iHR5N5uVqreY_^q|ad!Yb?MZhbXSdc#F;l_YcdBP#Dbi$9=OvO9ohXata+-WGZQ zm`-7`xxR(+*ZgcZtOoyc$7Pn%*$jGcKoex|YrH~tbVOJemEIcthG@*?B&2^crHShp zkN4H-yb)NreQBb<o+|qg=-8eS#1;ma27)M}Eg-6Rd9XSRM*#6t=9<yBgV}FFRUo&z zhnrL8^9A2wcJ2%~y`B3um!LdBM;$eCR4!QTp7aaTQy~kbmW$bJoZ0CyTJFi=l_*vt z-gWtEs6_`rm!ODdv+DV9th)?0`-c1mG`>X}68awR>Ym29cl0|Z_I<+=BxiNasrWD{ zMT5UI3;8Es4tKl886x~UV2opW=!*A}zM@3rqZ(gkBvhB(z_RxBk~$W%$pMnvSUo;+ zA%0^hUjNkAhsk>Qdy&=cM^}7l<!({dZI%o9_qwZiWBuKqVRdOsMVZ%GFJ1U^FcrLM z2_Fo87hzwzG%<Zno!VEWw!Hqz$uiH654(_*dswq~-S1H&z!KpgXk6!>n0QPISTpH! zC9Zis<b6GOr&l^C9#sUwu<T@__MbV$>H9;FuEH<B;bC!orayL{GcY%_72TG+Lm~Ud zonBJ8C-`Ce-f`=yYA7%1f2HG1)8lPp!O;JB)WpT9AeYjDMYQ=>8dIcgZEPsqdsg1z zb+EDEtp6$gQ36h*K1tuo5n-rn+9`D_UCyLKvN3cisiY@};QDy)tvQ|$gEk*Kh337Q zV5xWqroq=lrkgLnQX06Eg}1b#VCaW`!G2IyCWR8>>RHDn_;KYsTW3)&P}8$TYzWjT zAiF~G2mu9OS?fz-#g?p#3wDZl?EC@ZZE`20V$h)C<YesA4a--a-Fc3$g$TP_AZFe| z25O3vUiMjGYCnXmeYQ8CoElYX^9bm^Zw`7V#6o6w>3LQDrU3f{kI-IOPL|TbY0eT^ z1jhhtTzDWUFg&oWnN&pkuo9b10Zl<$zUtRTDb15O09jIxYrlYDV56<_CyGXxZi;(2 z5cB7A+(B{JgC^+0Xm4r%n1O434ZO(cpaUjnYc--F1?9{jA)Aq4V?ra8SHr(+IB3_* zy&P|c6)g>$f-sAZCn2Dk1%53=J+>{d82a(O3?GHcYHGHUC~d;D=Fj>aVCM^PHea>& z)Dce@j(@MP#nsZI;n-FcRBIeG%oX7C)l2Y|I0$WMWCO{mQ71$}wtx=m!G<v7UzRJo zjZK~02OErL@fs}vOBqi(?=I?}pL~o!{_F*XJ&&2*Y(@*}_Ai<V3|JGozduL|`}FHB z^x3*QMq+d7IC}P%Z(R+&gc^QIMmx3hk+V!ZaL6OZN-n3e58idG3vC1{pkQ!8&~F<y zO^JPAl{aA0D!++{Pn%w|>7qRa8H?v+7FH*3pnx38EdH<$K<%;2wT$@$-Sv5_;1T$) z{T`h3=5X#M*f*Fz+#%YiMO^Ucy-09CQG~f#h~rAmCTxaTD_KInrmGTP3VBO|p`Jk2 z55~Be9u0v>(L`<G*XCWquVu2CWbap&=K6j9TCsvUFw;!t26c}?lpKm)wf}YeRiO*? zg%S2e5)_f9VOdJsAKQ_-f=bA@$CB&2EZ78fEyuITt1_-+px$fZTmsY9N@sv8YK&o} z<0ARRp57B{Anc|ClH<nZ15lVkEOy)|m!M(;3v%sr41CudpOznpc&`sf^nyx?`S^OO zMT_@1-I9OD!Q)n#Z);>>p3W~_8=c=vH+<K>yRX*1U%`zPL4AO3(<9JQlk>e{TaYpc zB!yYrik)+fH%x73&~jOFSBrm-kLvUqgD{C`CkZmN#Z>T_Uk1$NNh~@GVjOAD*^6zQ zwkkq*;6e*-bpAT6Y%9TD15b_)yGrh?l|sT-3acNJgSvsslVOt-(X~%J;Nkc)#}H;( z_;y`bOA`=V4Tfcufr5zh7)QcQ0QOIpV*y8}U}nQX)|b;Jh4hZy==sj1m@p451xd`? z#zF`4n3Jtro1CmDjB+~EDY>Abd=(37a+lRWNg;g|SMCm8=0o+rE%kjKlDT+C-TM&5 zmuWl?59k}U_zSWtlZCj=mq7tAT-5Y%aoSNVl@em}Kq(SdD<lm7d!G2gZ{_qO%3(HV zqze9)icO#EhY={{sj#%px~p+yI3N8k(6evV_JUxRSNM}Ru7CUFqKJ$X{|SX5NU9kr zT%qjw6=hHz0xIiD1f#`^Qd~5kEr+QE#AE=UQ(76?Z}{Ssvq_;yAeyCi<%ZN>stIb0 zPs#HKiCYvQFqyT*Tl6f2%FY$LAZ6ErWw2w^gw2s^aaK6Pei0vfor1WW`aT<CbCkuB zzR&|LsMG}<LbhmFCQ+5->jE(SE49BnMJ^TK@-2Ed2UE>RY@#lEz+_JJ+NIZCG!MaS z0F+mV<NCJdT|9$&AJYub{LMgG8_uCDt_OsV8DtD>u<b9id>Hc!`gJFkak|)3K1`J9 zZahjgME6{j2zNhL-;;fZ+Z3Je%C~qC61;MHzva(k8?P=)2dFV-*0xlVKJgpYaCC4D zHS&$AA1<YU<zPhL!<Eb1&s;t~SV&o43BC;9?<<xg@T{#gs|}U^MrVxs(`{Q+8dbrh z;j>LcX-4J=>*rY{@5+w-Q_(doXrdooIZ-EeFkE2vmCz7xscH!??ba*<E=#}eRp6!$ z@29e-tya*`cd)L+QSoo;f}+<0yIs0MqqC84)F<rj%O&5Xx~p~GN@eCWbY_lyd^B7y zlGD*Ot$QtofO-ib{)(8zo<BphduNrmtg}iHH)xMA3nyw}rYw#@Gz{(lm@t%ypj?BE z_s0@Rzn$HP3?;#3M4^Ml{HT>0)XI3zP`@j;U=Z_ZLp-|xcv12?@oKMJDn2)pyqi-- zrtQ0fNUXID5EnCGbgG1`STbP}t}W)U_DlGheTOa$Sb@L8uDXK5rKhB%8a6u!s(j(0 z`fT9lPl5`qk%=TSItm4ZST~F8Q&JgQmt=h!Ilb_7;@OL5%)uNNadA>3CV?3-zs7W~ z2jO)b$b=~+EWY0!^YphH4bzE5z?L6+yzMDW1uLu<$W&0eww!7GBkBsoKX}1{QIunL z1Xnx!Bad2AAs+wB@Hu-fpnX#?3WsX+<uJL1yx3Y|Xw5C-3cEgnR-n815xKeM&Ix_@ znQ=xaj_4^=2xSb#RwAq2zv>P5k*ZPC;B_6d**2Cy)FkFCi%#rq>a&$iSEpm#F!J>g z6016}j!P`&-Up~fqQ51Xv0$^2wf_lZM7CRW1b7<AIyx`|d*GleLJ*TO8$o0ld_Z7` z`jEQ1X18Mr1`v}P_5Xz1G(^sHysNWHjkv0%8iL#>9-={*Mf3|d;`$8xaC)3RfNzCN z9A-P-1Z>Fi(Hz|piM0_LjiMh(4e!Xo)QMyme;VbIUL;4w62jR#^M+GViq56!z@?Xy zoDdmE)L8h<J{aX1`{Y>uv1zj8KB&@uLr;_wIFLEKVB?`D#-nzaBjrH*_3!Gd6UtLs z&3H?Rq?p2u_#~BmnUw}stgHwp^VH_V9H7E?2-#rQXbw7QQotxYUNTR(3wj0FQ`~d% zo%Q$iI7kv*^iU!{Pm(qXa<3F9YdBB)6UTTQdZ2;*A%teayV0EREOdJ5{@miTT(QNk z%0trrL8z$bAW~5r+sYNC2Dn5gRW6cCINexf(6)hK&pELs_U=da7^JCYw0rfPkj5VO zM8Ef@-OaxBM9gT#OFYg;UjbIs!z;9ApS|KI8!i9lgN2ZAwwr7Gg+E%KB?&OD(n;r- z<3=RX3Q-B%CL9P;%%l;sEeb^JF9>q6k-nK?n*u8SesFnh)^EFwMO|C)>2<rZK(=Ub z5zVU<*GPWy<BkSLe;jkcT@w3Kew=q(;|Ctuiq-s$J{|8wt-nL&3Y=S%>UF^Duo$p> zFb9;GWw$vZjvw8?LOuk8qUI{5$q_U^Gi>wmBa9za)x3QF>Ppl?uNCNl&CSOMXOp3_ zJw`$AwZI)`y)QW_5<XAu!HgYU4PabT%$Ty{97A=dfsX(#J62T(l=Gm(4HU3=Q=p9F zj6#$-dBP#reua=a)BWy~7LiQngNoS<Q|T>fydaCStkZ~}WzUx2TZr<O+8wiZCWZTO zI7i^wZ?NS5jBm4^9%SM+v0$c|fZk)!L0YyW%PP9b8=f3>&|&EDeD4S>o|^ee*Txfd z=hDWcfs`iok|a9vEJ03nQK4p5+E(;=#jB@p9?4>Vy7q@rR7>hqpI5-Wyc@ZZ^(c!a zfi<6LWQ}`LGS?E>eO}kwdQc|wjY7RJwha?rp{A4ogTm!ewsM0o`%_){!}U(2fw3@S zDxfE{eCLmJ@95n$Y)h_S)Ns0$VK}}g-E;S`agVKNr7~%h&&`>TGFvY6VKbNt6Y&*! z24U{OHaq^DkliO{=$lCDx@^VT^zN6(YR<|GKWY>#vYhRi`11F(56FzUhvatHZ^n(p zI*0YCe3*E#A9A1BAkWkkmP^Tk#{LKC%^5!pRW}6a?uvwJ1gF0JEWdhnL~cwa^_k?m zXIC~P=M*`MaUD|R6tSr6Vy=TWI^tTL^k8B6AzPeK!YnyItnXi*@O{cz$)?=3FsdDg z__Fx1vP7H#AA`WRIXe^!kC<jLrpHS?YnX=GdJw<ZrtoS`A0CM2IcXj8>6QhSo~J?g z6<`o1B%`_}>~zeUwTxzjTDDY@zxKOwEI8T=;^wV4uOBZq$MnV$rOqcK^1hLh{*%!Q z|JZFgmmH(+B5n)4qVb3wZm6I?<AKo5{LS2G_wNE0kWvCMr^>5dKXK39Jm2VkKnAyz z%}tUTQfZ$xUaI^nkueL^twz-P@-JKrswJkyLkOWiN7<A2T+A<sLRa$VrmBE?laY%V zmLGRrbXoQL;}>wOb~CgB$(DHiiVaruRrv(Fk;-rDz?^I^i}6dEtA%G(ifl9||Cm+o zzMp}F^ISwy&m$1G0MjPLHERByM}N_*EB+4UI%i)TH&{H2#d}v3(nl1O)8unpLgNu> z-NKN{GlGf$A<|?aLKhXd)O{(k^T5Zq@{y0^V_P9MUsLP?s(Gio^27Jh^zV;IkRUod zTANOflgES-xT=>V4#QM@jkR8)*n#P<sp+L%5B!k5`=;-8`+e}Azw*Z&B8n2cJfYrQ zvq`UUC<^ARcx~Uvi%#OZAhbk7`=GY`w)D|NHkk-!+E4t6VUq*@`^Jw)op_*ufIjzY z0K=gthVk4{<H<v7wHrsPf~yOLB$GVbJJ=PIG5l@UEXbM~I=4D_r1Qa}14WXA(<|qB zYH`hvO1q!Z1=?+zb8bd8|Ey6`>SMF|#m9(IUk>P_fAw?s&{ZCg{jQn*m)J}4mZS~- zhWNnvkZI%k{Z_DJyUUIe&ie#rcln|7XwMgyTBXuT2)1L(BI4$qui)&e)p6U2vgYop z#V#AIa~b<XcJ3hY<%`g6!h4E`(-_q9)yA#5xinCUa+l#xKe9+>tLefIi{-Mr_#S(l z-NtGb-xoK6xNFW8g><!E-gD+zPMH45SfK!>FOH61xS^G*RuhIH5!#cxOG2lX?rkKi zM<U3HNk%u2IS;g@Bi4p)oe-h3&$n@2X=mN$5&L;s|Gv>?%KIsKeD%B0y-{%hfNgq9 zR&Y7V(E#jUlmlw&T3<0%!k*pEMaK>p>nylb>ZP<$%`gpDVK0V%5sq(<$nD*-p-#8@ z_;Jdn#F1MP0&P+ZP^VU)O`aSFoGBQaaa-mDg;x_eaJT$D#~uULB#8E@w{Q3<4Ae~? zLn#PQ*xWZ+R1Dn6v+Qdn^0U&~DE7Z;k?`jpP|wNFj85NGTRmG73O)IooUEGy%j<B~ zA(u#;UbA6#vLJnp*Xn=JXKJPlOyyH#HP)5e;r?uz3f%j0%j>7s=V-%R5bJG926r^* zdV9sS|L&|Y_46%)40}S!bZM-W+ZZ#LD{_b&ZuR$6{)ronbjp*38zsURHB(Y-=Lt!c z>6(zl{rV3K{}n3P$+MvhXvdrBzL3cpUfdYt&4h62PV4J^S)bE0P1M%8`@Nmals!!E zW?Sqx7uR|Q<GW=VamuckyZ|y8LnYYH3hw^z@16nZS2FwcXj<r4u^6u++!h!9>Nof| z3mJ|M_?Fyp-I=f&la}5R$eSMb9{uBRPG{tvn8sDWKHJA}X}%x0!CYBT*b)K*kE*VQ zXNg2M0&}?{=K(Q?LD!3m55CykD3~JLOK84KDB>@K&^r%*q3CitVL$w?`V?Pv!^hQ3 z=R#!FTp9=Uwt9C|wEP-HxZMq`^VcAPK#C&VRzzxKig2XvLHk3v%uEn1ckbjDDZHm) znRIAN9SLFKOPt#S_LXO<G?x~?vkc-GPSI~H0q=>{vpwlFXkdnf9)9o(DMQV(4Z7k& zVMW`;-ljv>T*u5sVvBX;O9ceXDf}SxLowU(tpwg9(F??i(22TJ>TB_3kdzb%sxkK~ zbS>=J))r@b)OQj^>B>UkEY#WEiZjqs&E|u`TIbI-<^>-P*0VLDf}8;Emnd+4yoMAQ z)Cg{}GCLn0lIn2$)lH66DKF$c5ud@u%)THSkII069ggpwA_He-HLsO~D!N)Qzi^%2 zi3(9DpoMAxnfb?9OD&fqtI;yyaD3lR@(7O97BVFqLsVKfxdRg_XA7F<wV%QAYXNq2 z@MN|NhX+t9uK{<Dis|=D6cy2$+=o*Z0qpiT(?>2ru)C*pQA-t1uKs|ZJiqF$UCT@R zriW+QF?UWppExBLADYDm)Fk9wXXa)H+t#idqfXrjM`;Qi3vbk*<(qQ7WLXxIWTC2H z{JT9IDfn>sGVv@hc|;l<uOa;JG5@8j{UIIy%N5mu_=j2iOE*FOtM`9tD`?FBeeyr5 z=U;Xa7PvP5T~Ab+E)QI#|IYaT)ddOJqjBx)*l-vJtiJo*#G<OC>9*SMEmp6URaJ?r ztEWg)7TKOI*OSxJ(;Hc>d`ZpbjZgzuLW~5sO`1rEJU};6JY(bb4Z?5O&^!AzebcJG zJ-2tMxxH`vRNz+d09Wa(s0Z!y6@7TSf(T-J)XiO5?#P?>zfA6bnUEe|$e0u;in_Ot z*ixdweP{1q|3xS(`yRz2x{AVE`-QZ~kp`8k9F--BfVnRRB`SeTr9CjcoNNPv^bcA6 zO8WGO;T%hFxQ~#L3O&5IweE;tf9WYrk-+W|hq^Mjxk5Y7ARXU@m(S~t)6+X*Iue2g z(~IG*Z~C@>d%n2c^wpgppe5*$QBhn#ToH!EKSoa3gF6HFH#B>h6tmHFW(=rM1qp{| z#v((S0G-}EHTA&VDhls5kXM56DpZA(+$tMyFSw99m#4z(l*drww(Kku0CD-hp=yVu zb~z{|zUh?c=|of4w<yEkXt&PlDID<L)-Q~l<DRpc5auOFt)`FPsQwkR63TJScoSFX z_aJjoX?nrMC}L*RjGFR+_)hc-UysB`#6>s~!fzYetsXd?2AG6QbO&?rUNG;!K8ZSO zr@WAy8jleX&p-y(>d=?S)N1<o`_C5vQluhAjh%<5+QR9~r6S|LURhMv52YI`)w2Gf zAc>BH-nVRNySi_BFON9<?@R!I&t^|38u3Tqdv8-N`a<Vrdh&bh@}z`^M>#juc<q4K zojtd<Wbr!qj_9iZ5(7;pe1<s$sn^)*4zo`BILY{IkGW43No%OAK5drUC;u@ml$G+{ z6-qII^IE}E4@1m2^)cSKhf)4@6qxv$XYvMBndb8Hq?z5Q5yk=6GgD`~QQPVCWfN+! z>V}G<xVmXcg*W%ESEhi>d%T(s52M`z+tDsksy3*KEd6i~tCHWGC~mnCeMmAiWyPh< zd{cgAL?-6krv7^f;hj{oI<wPU+dyBQ7X790&n-yBt@W&rFbGq25y_IT?U+o(4gOU! zJ(PAkqlYHZ%RUGrauVpe_bL6l9v@&&lxm2Pj>-13*e?!0o~}IjO5y1<8-zHx(^Law zt~UB)B8R}uzM>rA(Ks%;D`=Z{9>b%GXJA_r4n2O!ra^9i<5BsKwQvIQg#W>i5fwR? z_uvO1@5UbGYf+-N;{&AQ^uvwkOcQ?A#HgDgBd~U(5o88HUUXIPQ-n?j18+@jszcT2 z4F@Ed#1VDVWP$l^uQNU~hTZwBMYSfsYnv22ku=pQM>jk1RJA|ZcIh8Rm?`K)qM(?4 zwP}3S!B!E}8@2l;&r~b&!o>eSx;yiKsJ}gqmwm~WHCq{#-Q;FV3?^$y#6*d)B;U%C zYRp)tu|)=nB$K5ghA(5!Ff*3Mz9iWu#w2SQ46-kCKi_+Qxqrhwf5AEDea?G%zR%;l z;_K7>z4gLPh6c$K&Zq8|%FdS<HPcJwC~n{6Tt*Lt_DGro3bM?}()$sjFod|{IL$~R z(^aQNjdE6VfPmyRHY(6~2@Rk6ZIn3=(?>aVK}t$2?%X08)7%#Wjn86hxuJJMIzn^d zA$Du8Z~9m=gq!=^#&Wej{&P0{fvaI0m8*)^mH7yotIEpPQtiJ~uK!Z*51)J)bz9+z z*+P<Sg~+bNvnG3hYUX)wimr+YzWuC!`UFoWDfYn&aOVESqkjD}r%Vla=bKX6j$aE_ zez>XNZ}-YNd6v>7>NWdKl%m3~GS(nWSdSZo9@<H6C3^9*YTfywbj-O*O{VnWGb@W+ z)c%wF%&X_d*`el4c`pAnWgj=T$V1m|KPmeN#beeK2tumW1J3|U5_N`qpet!vU+Qr4 z2h^{0zPvM0(LZ{^L-hW&5o9Kt%|4vWGI2htO6waQYp=6)P~PP9(94$@uPJN`8)9VI z4D*~-5VJOHlF!@cP?i6iwNoFsFq~M3U}E1*hy76IRkWbDFDI=P2sy<i+4{QPoH%;a zsqu4>t*i)=+8j)Np<8-UaY>01V&tZD=a%0e?+-44S&bV0TIe_*4s31-6_<*L6Z!)F zP(QE8)wq^K;FQRj)dd_u-?Ph9oEuTV(py4Gpkkn`#XqLb2f1J~rV$Rk@Ym@ZkyXdE zf1ZDPph)!2SkzOK1*F8SUlb|$Td)WY4WNakn-#AaAd~af*b~GKX-D==PPS6yyE}_j zc@)Jw$f!$1R$PYouo8MXMYSMFraNFZ#6R3}=Gr}8f(xW=b&EVJlKe_V$v?-HJ+`r} z-Yd6x9U|$_5byczk>4-n8UITYH$#Us>;6vQtJEw6d(*CVgX-wUE8P@f7W~aqLbT;! z(kCTvKLmeB%z7#%i>xfT14kcengronB(fGd!EKkBJN@;L)qn^@CIg0`I!o^`iH}zG zFBZ9)&E0p8guv+SZ9!Km*FXfRcP*>?0vE_iQQB?mYOsa*??NlWVq&+>J3aAjxsO|O zF+K}(kSt+^9Us^C_2Uwj=mKJVcAvXK0&bbY5<;!!HI6Ir_C|d-#|o0Iy`%N<6%|H5 z{3OWXtyb>w6WG)Kv<iuLz;8C`iZV=byx>?8K{83_((|tBbCXsivD@*9%~@&#eJ%+Z zL(tHnR%!F|H7#L!a(T8a@o66W0+1tDb5weySB;SrHvG99PhCp7x5C_lR*!F#DhVsy zZU~VpZoFsv#ZaqVHjRCDq^C?UVr&?-Z%1qiruIFGXcOG!4KX(pxqx5b5n&qTGsyc2 zg1P;S=4!7qGQ>S8S7TM8>rk^%7tBD62un`dQe*8n_0d!BO7{CE9@(tqVLK1`AF6lE zJTG7M6XQX5)|L55%M1R(V2~SVUML^&;>0k#_G2UXiR78m01F1?p~Q!J7I`O(hNy~( zMC;rVDZwJowfh>j8#jvfm`=nQdIU98#9C$|wnn_iizqOyDC&iPdmH)Ip5PLKOvSka zIkThV(zjN@Z;HKj%Xj0=wKz^Z{`1;be}%l)dIJmk<lv0FhdRXF9u4G^AH>k*CR)A7 zC8EEp(cWknFINNN+pC()$&46C+lo4glFNOq^1l2|4BbpkYjx#ygQsp@vH3<?=|i2$ zV~c@LsLyZGai*fvLL%o&2IwsULBfGCa7%QXPiw{;%yXul@i0yH!EvZf^@o3@&fT4Q zYF%46@(MqOyYG<R7<xOUt@lD@=WJ;eE*_Sr@`IYFNdyX7X#~v4#%)k+xj)C%vj{E; zb;c}A@I%5d_mOx&2z4?=t)mV;wqPRVDz<Gf(-d_wqJd*{$3lo$wT}K=-BH3SF4Bu; zPxiuvOxf|aCrg7J@y!(Ut<i1Ef`IJ@^66327Sl8Y`9)K`+>Jjz<B!N3=^=;OA5Q`9 z^LF-5Q^132bL0|w`!XVV5`sDiNH_7;#Z$73FS(U{IJSBv6IA%dB|F?xx~lNy7A5Os zB~P{cQa)3udpXcxHu>q~q1O3oa8i<22?sWS{Tm{G@P4+vU@rc%xn3!D;T!x$3+%i} z*24VfF8hoW17mhy>pP9;#zk11DD2d((2@X>tWoQNRQ#ipV+8X2P40w$v|xFDty&(v z%+klCZq{Wm7#NNDplN|{lh@bPOVm3*CrA+gda@O=bI=)+T)fy@ycQL=^-R*RtG`Ph z&ixbo$nK89yLy6LbPUZ?D8qwtrVIz9*z5P^F{o=&1&Ln;@iqp(SBNNvcC|^E?wMJv zL+{9l8`$3L$G0nKDB2UV-o0w!16CGl^c*+w{g$ZeKwELPec+%{j8#tZ^iy>G^RKOC z2|$z5be-AfXd^w%^Hy<mn3lr8FVz-c6p?W_nZA9NcmZy#c6Uc+1p>wDfq+#D9MxvN zlz=JCsEaCyF}+ZtdqNd2N-R|6%UH`S?S|iCB-ziaz2nUIYR>qLMbO~)m+Hm#ha9PB zcH-l$%2WF=sn}0;ZUa_-t#nXhQxt-OaHiUT0U<T(W+X7lxHNpv_3-CK8=^z>&!5mc zLGH)$U?+Z7-@QA9h2=FVA-g(em!PZ#v4`0dQ7;{S8{-$T+gV6a!$?D(RF8!E2pxA$ zn#jmVT-T*P@$Q|oIX<snR|I$@;J;5=X2<>mouB6ehe0qxl%&VY-R6H%dhS$UBKYju zGtM`I;j&V8QX9h}TI~y=X@ixHtIGw$zJvRTI!QXgFq6Q`8Q&`Ysw<ZBAPF74re$S! zU-4o;=%j`#<h=zXo`g9gUgLFLc`X&{KLv<xcq{$Hu`rN>cx1Z+UOiT}<8dG-dIg*K z-aNnGjGLpOivEXw618h{VTkmw=C^*o!VWk4ActomFtNF1t$-)+Fy+-E!S-6s+l(hp zr*D*&zxOnZm_CEPYL}zdWU60&*DQ1vrK9N6vn0Nm<ZRIJQC-4!|M}F#pm#PjOX1eV z)uj&*wuaSO5kwmd9r}WBzE$qC2dERcW$bhHcGP7Khbg0wis`#S@LKhdUv%mrdloTB zYv9!wxE2A#$bwM79B;V`zmPGj-|H9sH8~=U&oTLf>~5z$^&rI7*rduFZ#0W|)u1?y zaHp?6TRp9GHbN&_TGPS?rFq>BqO{&m+co6{i~T7T)@+lJmO5t?S`h#dA`CR2EmJO+ zsg-v;1o4$?n*V%`XQ85(rd5hSy5$m4d4KCvr%JMJ9Ui@#bn8r8m*Ze%@S{h~M>?hk z_gkj;JInnXi9Ih(65gI(OMCsaVm^`<EVVPH9;H+v*j(3#8BW%J!!yr*bi9tmyDOpM z_1FnAP-Ja@AFrRDcTO-7*{%;s-=*mfRLV`h^;a`dokP78;6xqS58)@Jt2=(LRKC$m zls+4t+n8@9L1^lYrl#MNyz07?&#~83ZXqTD=?V1u)RlMpu(_N3NvSrJ<bg>u{_;LM zF67)s{pR!ubT>I=|7Ki(-y+I+KgXZ3flKI~7t+Ll>L$bovrZtVb?~E`ucmxsd>mqr zdKID|IN!NL?d^$AOB;7C0gv~uHi}Tarjv{R%h3b^5}%0pZ3o%4F6UcYKm~s-B^3{8 z${%jYvHW%%e}8hQ{>5KdZ7@d|PZsx5w)EztZG-fOAL1lKCS9w1OhFy`2u8{XOW-25 zCK>av`rBsb`=`m(;2WzO$%AfrWREXr-X?3@SYk^xy4c5zpCV7*28b<l@fcy}0c-eW z*s@?!E-O55HfG7qbe>Z2buwbrSLl(Y=s3Y|6CC4~d;=rYi)N&;=0*NER*YJi4p_rg z>}C!u;CQN-E6B6>ml214>PGV?jKKC2X@0w{Js=9Xgl7j08Q5Tc?2T#cp^6{B2BgZF z9C<3514)FD@5h~REc-9?+Unbpg^#Vdj^U^I&m*fMw~&^sBSa4*xNgF0FzW(xN{9Gi zN!(R2jLzU!BBkt=GTU41G66oJn<Ff1g*6xh{;;3YT@c<KQAR7Y0Z*`jZdUHb3;?^o zcH*#^BV0RRm|h=PA+`oaU;L`24wS#y#l11Q8XH~C?mpJxd%V;!`UkZ&My0a*-GYPn z>ww#pO`(|Et~>gk(gfL(ekHBu4%3fKN@lCFrKCRQN?6$Jnavvj6OiZrS&)|EwUZH- zFcx-<7Duv{{i@N2vEka~^6v4~p^b_5o)3ef#|QRzKGo>D7iGQJeEQ!?x<uJt_LmHl z2{$95{00X+nJL1UE6MRM1I&A7*r}%7!Hw6$x{oU@S*ZvLPCORbC<iX7kR`_OUcvE# zj)?fI7+b?vPJENTL<=vW!Wfk~Exs22FO>I$<+@_uHF#Gvi*fT@;N>5gayI*uRHp>K zdz{e|D=q5qZ^=51m8ag8d;~(vXUBi20uiyN-`(>7QWM7!Jec`LkXrV4Lu-{d><X|? z?Ev3-Aw|8?uAx5Ud^K*O7KO;rc9(EI4)C9=Pl0@4FdD^bT^zbxn3$P4v>`{-V6A85 y5%x*5^I+~Nz{~6Y4{>S>{trI-|D;P&y!&YTtIF`t3Q)Bpz_7Knw<w2tM*kbhpn&oK literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Github_release_button.png b/docs/contribute/general/_assets/Github_release_button.png new file mode 100644 index 0000000000000000000000000000000000000000..7232e6366c982b77583b426890a477d32f670935 GIT binary patch literal 243699 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¥g^+8p~z%meqtRh5dw;Aij#6_6YLU6gE;_R^VKpS{HwQ>Sv>ht<| z>F8N4rpsEUSb|Sx*?<Gys!Kj(8Ni6jnpFr*@5NjLfcWeLcWcBT#od-N<zk^|4tR2z z3OKE0vAO(YcV?(>0wx`W6usbnmpF_bG{+t8jo?3V<9nf++G#<ptAeFQFGkh@L&3u$ zwqHAWdY%DG&QCZZ<7>;y{kLL98a<x(B@O)QJrWq$aOVX`a2NZTG^T2|xu^L<6heDP z1Q^C;L*8&k>rKF$x0)H*oPCh|W81@Qeb-keRXR(xf4#9ZfgI+p;TNr<;@^!egfRA- z9rqQr+D$vO#nz=uI9~Xa2x627-erhf-Q1c~+^BVFh@j>!MUtnUaE|$I$~T78L9wOo zzTWRYc>S4nEw>3PZ*0$yY}K2lH$C($5OsRsgKPdRTy3#rwXyErd{MxEez{(KR8scB z$}`*~dN-cdiq+5_;rw=^-wds_HYgW`H+~zOW}i3;pNOrK*^7F#7rf#ho8I__^@km! z+2mXcrsMX!__7Mvtkr25Wx=`Y`|!~W?*QIWV6+MKDL|1yl}TqYqPl<EW8hJVv{l)B zj}f#%_~_l|6_dpv*=FlHEwQ}_P5wFa`Z>opzH-7(i=oBp;h^@OR|bucfsujU=7+T) zHotcZlms7^dww6#b5Ly=qk|HS(&O>PJ!u08E9Ey%x3~!Ii^p-h_S=#8RE@gw#+^Y6 z@1R&#eM1-G>l}k>!uVMT>}7Cg)T(554cLBWY-mOz=RI=Zp%);Rh+6HK^JNuyr8K<q z@*PpyRpicu>)3?x(NK>3BrCO{jzUjWRd&!o=;YfTyd{*aG_IM;(0|PHS6>ZEOzdsW zWRx~*t*%a${n4x1<j0mrcy6e|X8t!WhPcnkppCS$_>^CimIy?)j!VuA(sLf{OfyEc zJ-*1xyC;wqpQT&DAzkri^4@?^4#IEQf-#Z7OTD1#{70CrBDo?$aa%dcF!a@jm9C*| z>J>^*5Z}S-NcV^RsuJHC30k`ozNpn_No>-K5k6?ctOSw*`0PN28L6buwQyczjYDag zt0$wcSO4*ebB^3m^hDl>RYZ%`2CK7Bx}X05!-C+q8V<j;8SYe*D<2xcH^0*pl|)zK zq`t{`g-ntr3ZV1T)z8YA0(Y-aQ?#$N=PJ9?0lY8ehw`TS{(h}%Zeho^*5RxG2bbQ7 zU+o&3i-9wf_tD5T|9!drAj3Xst3D0;a>(8RTmIF7Vu{^w1o$E2e&-J8gxH%Cy#Am{ zT`esQ<D=_-GBg5t%FTAvxnR)&`}n)8z{z~yX6Q}h1&gWa?E;kzPutt6I}o2b1-?DS zw`(Fg$^ufmJ^OW_=|!#b<KsR?B2A{B9F?4aJ+)}`h=x9ku(Yx|j`{tYc{SOVcPK*I z8(fa_mL7T$7i95=>Bc^lA}z7#W<16Qb;qH)Rcff*|Mtn8&m@)~vG1sJWqRiozSDk) zy_Bu%!pU;q!#UJ<q$uo9AHo1;fAB2rqhx~H>^#N+dx|MQ?;wzvjK|WuXiI~2;xy4p z11(lF(SVHpsx<Fuc0w3+IpT!1*_zskZcRvrwtF<x80-kN6y7v6`fxDqIzw<2ybZCc zoA;})64rK<JaStzY1qv6oSzAx56R?)KW&J7;IxB(hO@g#_9>s?l~i4MZu9ke*ha1e zV}$Uz-GwxsjBD1SSL&b6^%kfQ6Vd5Sx6HYu1>bbO2r1gqKG_1tAA4Y0w(|-F`Xx%I za?s#r)X2_EqAV@vqQAqPFLkbpX)fOL@yQ?8E)8`p{bMpO*|*`i*S;%h9ON?G=KHq& zEs5SHP%^;dInKz;xv;B$^NueXyQs_Dx*W~!bN;zXuL8fU_6kf3LL9{11l3-g+Iti1 zD1E#Og*%SV1k5cLiPXDgM2xgZJx@~wvkCak+q5Qo>R6tE`RtCjG`3}Jkf;^q&kvZ_ z<QA04-f+r1x5uXrntuDJ%y)M`aAD?_W5*mPe6L^i&a}iFhJ~PGT`H@cfG^?D+<G^% z%)Qxq5Xoe<W6OdMnK?GPGyd`R(QFX?nHAbmSFvQeG4Y$}FZclElFTuC9ZSN@jf0Ot z<Ucvr)V1s+7DUz}zK9W|wY_sSWmkPB<%ayT&OGy)j?<oQL3$2dVY{W55+a+biZP?U z2kTHaqBK4kSrNwjOwHmI9h&BveD=>b>p3?+DUSKL=Kh}bh)iB!jL@4@0z+--=v8{q zs2xuw91Ik>N&+^W2`1Vw^}@k57W+gARxi(`XG?jdzyHJl-JX<r@ru9HToLez-9Lok z@6eb7x8S{QihD=<*Gdvsq2}{!cT~DSmfzBw*SO%}yDi6z`^ZMKNl3=@oHzLS{#DkK z?*=_&q4ON@eF5+rQIaEqSXQj%LwYgvG1jcv4^Y|((8rwIF!O8IXfu4hoV(PUU1Hof z(kc2B9r)2;B4p&f9!56Z1#Kf-b<~z^|Fn@fdaY4DX~55Kp_E!TY_-;VEiK3)?e0B2 zvE|&l_Sf^br;wNlH4q#2vl|D2+N<+?bEj>i?m8Vn%Gi})>_5$jPA*Xk9cWiscrea* zI|#Qsx52yuy?gVT)LPIF?eXI8?&J|;gwobKSLh<14k9#(_%20SzZdgD8fJ9u1IURz zc+fGmwmSV7X=(_*(L>r%xTtNUAp+?DS94g*9|oRfw<KOYl-z1F6!h>p4zo|`06p&I zo)YvMpW(h-FX4WZHWL4+I`1pc_+8T2n9CHTH~<<D4Jzy?-uJ-vncGElRd`^dmU*fu z-*$8nTP!&TWLyxftmfn>>47>ln{<rlhTo50=jXI^1^C1r9yM6R8u8um+>qtC?PQJc z%N!0>GiaS1V&`NY-7P5S@sROtd9#3zey{k86h}3T(WP%h={i1sVLbN@Bx;ln*wz=N zNs13Ur!Jx9pFfWBR_Kusj4PeY;9rTDA$DmD)Lj5II39~stLrR#8Fc=bs&Tn$vh}Tb z@<yrQ*Q&OwmT5>)JI6edMmnVnCV#PX#{PW*UP4i};duxd#AYY~`8Zy#2Nw?2ZPqZG zNs!Q399LZ3lTTOY^i|0LBvoZxmR`?Pp)4$`6$jWL8~%dlAtD0PMS_rVnd*g=RZ7lX zhu?GOLyH;o>F+bPoxVO*RVa3R_x^X=?V_`ygvj-CG}umzel@{4#pt~VsH5Xbf_MG5 zrr%xZoopabqGM{MIPVO9*jDU%`ghzjX=@>Wxpb)~5$gwr3wI|3geWcoOlid_i6mCn zKWs-w2pfUm?0KP+2J%6*<Kd=a0fdxOjUbOIrIei<V@1Sw(q@a-@a_f2ya*?Y+&VM; zCzD@-xFdCrn$!{?N6Wr{l0hdGweN#Hb=VF8nW?L^9PkrY)RF_~=Ypu2pl%^R!F$a# zfmaWMb-+zJXiXPI|KvX*>MzSC0t>NFt$w%QLrtul+B?_;WXYOaGO!*-nUz=<lA_{I z!G1zKKL*(asSg-B>q5wFypg^;rWNXnrmeC^*%pwm3zz}4VQ@6WNfj@69qUJK6EKVB zo=@5E+pMn}4BMEwoij0xHA0*NCZgtA#FjQ?;c><E;76~6lU?~XabKjKnsHQceE+Kd zCU5PNwy=%+R#cS3EB(vAugO!X`>*W+(%ckpO=MF$F>IdujKDF%q<fhY?6LgoN_<aO z)9-GMtysE`I~h+7!XDaW*T!R|7tsX$mKNd?ArULRcbvD)23b&dxc!xM!CeuJGf%Rt z!wv}J=tJg>ei+&bEtex&J@!RqVLrcD=*3%TIN<l>wCv7KytWGG6(hu3y;@SQjK0Gp z{cPtVilo$Aw<ZmwkuuCAPL8?tQVqP=Rlo~FS8~z<#(mb?(yR22y?*~xa)z0aU&TR= zZQ%y|p+38-zHfX3nR#ArYoKfhN*CXs)31j_rO6rma;vTz3yUj>Y6O*pIlV-ey#i<W zd4yY0=#PiY8LihTcl4C_c(&=6622@$SsBBnT%asDhQAsrD{bKg71DdUOiK8y))C8h zx2%ad@(Sn&w~OpG%u5R%p(a1@#=7Ekn7*-;nuxqGiC_FqV`O62!edt}DxaU?P_Bm2 zv>1tpmZ5tU`@Wfd$n_!n-kW?Q+Fcx5-fD(!)To(qC@{t^A1!BL6Wek`q~E$d_Vf60 zNON^=N=BU7;bY2?fOmyvoRnEr)sG)yllQ&C*(G12X$K`*Y_~}ss7oKxOwcL!2eKE# z6PO41Yh+z34y9Nhstxr}uW`Z+7iXy=1x1kGDJ0eyZ&Q52s41cPfFMKN-(2FXPeU5* zPO3tf)A3@fa`P15%@naE8u{kk+UrLwFF;YSlAdoaB>ganK({fZUW1z<i~6|QyYl+9 zV=LI80i-#sob#Pl8mX_kSJ_*e(z>1<3`bEqmk)j%R55xH+D(&|cG<4^6?t7$#wkQ5 z0p4(^+**KeTo5Q3JpnncyI-E>AdOVZdzfpp-KpQ(L?K$LBu6WTvp$KnPJ_wh4am2R z1Ya2$hnH*n4JL@=Hjtfe;j~9<Sa}MkXKvftO80+nS(dQ!S+mEF!=JvdZ?(SaZ%5vR zZI?^NPK3}(@YDC~2t84KC0=yM=eeRlSyt=ky{4SPMD`i39W=VC3jR?L6Y^Q_mgeAX zhE;I_ys}zzGX4twLqnFE2`<H)2%=75F>L3ApRvi~jIrQ_rdz#q(0e_H5k2mZej5VA zOiaL=0IlU2mP-!l@uV+#@T(pKB5N%is_Ie7U*}@HvdtYqTW#sM6E47<qu*Qh9e;P= z-UQv&Ee~HnD72Fmn`p1M5LIa_TwrH&&~%@$L%rFYiL{PqR?CyJr9PM<eHf|>bc3yw zD*pjz6($vas7OQy4DEW24zOaky_UhSz2Zbw*F9+&RbIWW)|qPmFkKn3*3oLrOpWkY zRfZQ{$I-sE<n6?D`UOQj5T@sRqn&Mmery4CmHM-<sZ~F>WqNd_D?3g+3WrOt4&Neq zp5T4g%IamFLW#p#ngi!rFAM*4>rg0@c6;DxnT~>v7aaA~o-inSWXd56XAXt8=o(nI zto01<)p*xUvRO$JP+TyNbJrTCO@Y+pcbD?hq-hYpYO!`@EU78y8D#UzWHjav@fMu? zzENlCoSr>GCVy0w3BDeAtwgO?y{Yci4J^di|9M8T5E!=t(vN4^kER!MH^8lYGJ*qW z2Q@L~wHsMmrRib5!8D&tCvHpp8rLd4{L}TYbbr~>uH9s^U=h?LIGT`p6#Gc8ecJ8d zrKZKKwTxJvIu#asGI&z-L2q+;tp>lMQgCE4Z0Bz;kI8`BtB=?@(V1bnyHZFFGDjcX zKi4SUZ_<SNJ&<tPva3JM&R<`71wMZgc(1zfqchW90>bN0Abm@%pBtXGHIVBAj#p6D zQhWYuBzW`Zw#!@09z<8Csc+5v&ez6{S2$k22Sq+>?UpNN=F4Zio6^R^n*lnZ8RFwP zN+St$=id44F7U2Hv~F39B8X|kXu+}N(LNc^z0vZz+PpM2iYk4#jk`k1hY_S8B=2@t z{BeV-Yv0FAS?}fN+nnM*%7(Cd33iHH71C{yH?#K(@iiolZ&%;QIp4rur~P0(9Yg9N zr}uy6fhERE8QBpVg@k2{YRr%H>+OothAxCZCD1Ei>j7tC-K|1_X!JE(A)Xdllhv%9 zZ2y^yK>dZA1t7-uDWaX+;Jf(c;ljtQR<m@Gn%Fh*4T~j~(Of73;u!X%u6p71!f{?T zkstB=U@7cP=(HKV(DU-=c0aoIp^SH2f__cB2-OupHy_qDH(s1c?4r^BygK4byf6E4 z^7m1RcfXK*IP6++%IkBG!^v?2KdRGxlXALmTJI8C{p(D9dA`!oG@4lGs7H_w*bF(d z1l6rZG`QhD7v5h?Asr9+3Oi)|%-A5Se9+*6t9x6YiPm2vZI`l!|9hLLs<-ieX3uPO z8+m6xv7K}6IG4C*e=ut)3B*f18Sk>TZw78}wwd`CN_AfEqw3_}@1#<kwvE0b)0%eS zaCt|wV36KvOOpDamzPY*q>S@jPTZ|Q`e1(ZV+7g0(4-zttexhjkrF_=G~!Lyqn>Ez z!K-H{p;swmUMZr)b3)4|n4fC1moh>6UaIlczaL)H$MGs+TaWi)P;c0BlOQ1;$S*a# z@z8Z}RDP3WaG@m(4fl$wrjI7mB)1hiQYDz5<A&=xVm$s3sKq7fm7<o97WN;OPQ58L z8`tv1nIFBp4EVO7H{S5tk>bs*zIPb0+lttIO_rF6sq80m4cpf&i)MGviE1uoAw|V{ zHM(p=Ct-gsr&01`tAa-uH$>JiK6tS+p)kOPsJOeK#7i#a8@CNje)@Q%`ICoXN7sIe zuB`v)<=fYIv<7<O>^whe8gN^ET#J!`(^|nUxPspdO#S+DeOgo6-plF7?@S4}47^H* z^V$W^?459sfi&dDvGh~2pU8yh3LK@=5m@W1GP01{mG7kZzTIz`xA#lQ(%ydH!H+%p zU7LTB3Ei<%-i7T9K!<+Yr8_n_yQl-cnPA0)B*BfIpFfTg?h?)q8o8Nk<~4bT0W@py zm*1X~N4TzWb8d0N)x-FZ#rI!<Wxe{a(L<(2Z*VI-HDY!vTS$xn=$1)3>9Q>x75hJD zmHTSY-KhA&jRKvOxRT)<M1_?P-2X_gvvd~C^l=<N)VyAUvcgQVOMSVf-pG=FA#IWN zqD<=%$kA(Qd+V~tk3iN6rxi&!Y1TSX9m`xuC3Ew?a&iDN2h#S{Anty<`A5q!8)Oqe z7qL4k&;Fy?qilxnDyr-H!ipvTSQ}E*p>`^`?ur1vC;r^hF_7`4c48@9q83y-B3T&* zv3XCcB3m7k=$lPX=JRSDvbxjb_vbQ#uYIF_O4#Z10B;~t3=U8#ojdW+TVmUdt{oPm zn0{%xI?+;LzI9JVP#MNFnFAWK$dVYpb193PMM9u}<+3u^56a#ZAwC=MvJ9DeLfX~? z-I{C#Hw}7sM*#kbYx~;jO3O_gC4F|Z^jDH$Y}kb;A}j{gt`1rmq7HLZejYYH>U4Cw zVAZR=*+jg3Go5;`(Y@*QFj+AoRrAvP{3d3A)gU2Td;50XpU=*oImK=*1yUwlZR=Cr zfY*#x?T}1ePI!@`|9b0#-O-3|f!zXwU9u5~HMMFvx<Ec_<bt?##m1W`f2W{m<tCFa zmM}bU&}o*U;Su6LJAVeAS$rY3rRwYP!?@O|t?F`4k$Lqdv2x{?=>00<5bB>mJZ8nF zB)R;Thm?zrPTu~lk0V=U5+B)B!Ir|(1MtpoC_s?tnE)nODIWia6TZGwVrF(UTPU&d z{xSER%lHn)I;bNf7yLP`_Gnmn^_)6m2T)TQfxMIVnWkL{;Rei0)c=^5)uO|@pIgzU zmw)UdZIEY1Z9Sq!a`cwJt*6yuE(Jh#S_%XlZ?fI7N?rV3SnIb&BvAW&zyE;^`+as? z?K9TvH|2q6Ki0po;0P<8hMNBWn3PO`%pM2<6)W7!C`PZKI$^s|yK%?uN|1h0dZG9J zPV&`e@GyFDX8+ftlP)^b5Zl~4YI`fNMD-7~FOW&WwTthv$A2UBlo+tGI`iw(IK`+| z-*sU=yVV|~=LQ0S(yuYRbe?hJsIgH1B4xS9MEyJSs#v)R*dFTlSWx7!_q=$b{b!_J z&8A$A>lBWGv2{1hxLY#x{w?eno_e+1*joV}WX~8S`=|fehn8vut_g=I{&)Im4&{)Y ze!<|~p{|C#L8HWSf6RND*1Xh9?=uW@kka8#l_4HOtXaLj6GkSV{05l1T6AmnW315g zNiY>NF$lqUGot<W%FQFy!;@{j?fArBV*6Y4>^_OH2M@t)4_*{1>^{S#IP{(OC3b~a z-doh9M-8(H4mXgkGWhfxeM(X(g>Bl1mcAJertqaa?(#SzPiyC<R9?}4B6vYRZSqFH zzVX&79aK6!-5-i#awZ-U_SQuiz`KKIo1=tRY`3>TQsgD#O+VypVXlLCRYC5DwnNTc zjT@yCgio|`un{c(R~xgVXm;;CnK!6ZCo}RyaW?g?gF3jTE7f^-aJ{pXi<2)2vG#df zol`36E`deLuai~qZpkBWDeK!77!tL@Wo9n1IC?yk)zFq0*LMrzI8Nsh^)8S4$GmpK zfQ(rcT0#d`;MfCuJisPQqw0Nlsahv=H@>farj2MWxRnrp$8c@cL}8guCv+>Jl+_Nw zL*Rk2O<9%LViTxJBxs`t?$@mM4hX7K=G5=aomXHq3W_1g7&?)<5^BA9v{rM3e#7^n zDa-GbW-r}QIB;}+N7b{QcKEK%OQTbos)Y}_elA@WF*sKAf)i@%?E5LKJRWUS@R5+; z@Z%d6Agz19z(fcqPYw*kDQ+@ees+Qe-lZSi4#7vEQD4|<FZ;9Tb8zHsm`qX?u-R}2 zIMbD6dV`@8+oUE7nY}Ma(YqNlb|61Ijg<+xuJ(9Pus|V>L{km{$*>mpqb4l4)KjKW zm6it**L`g4mL6AD_kZt?mVJD$knO%=BAdis*q1BoN}Bsu3?9gErTBYwgLfb^FztjJ z+559%+g9PRjg%v}3*2yC)9UP{@7~}wlh>W#D4;Oq?WG$jSQGGc#$6PT{y&k#_2)QV zNuMv}XUt4vk%-9JqeE-SOL;6F>CtJg5yFg~e}-(D2bb3DnX007>otNV17L|!h(80y zIajO`*_!Wq_8GXQq&^<Ae}UnKyEwgHu^uxz1e`hU2_`c`eZND$m04b@?TH1<jIb!} zSCXmt9$I|+=!jfg#aG$2tjuS9wGDrX?_0{j)HHHJ*RHR>Cv9(Ou3ot{%{i!B@&GPe zW8zhb_T-Y<N?z?;6%Q|K@q4&gQ{QxV64rVc(wbf?kY3MhV?QL5gz%TmMq+5DBkwgx z$Ldd-Bm{Nz(5Ql6h*TZWndR{o^h+kJE?w99^6+<LMAX^FO9>I+v*OX3g%Y8=0~!*# zArn(F+(yEWzB%sR*$J-_D4ISRTKsxLj#-nH&!tK;xT!JvDeb8A2~gEj0;*Rz!&;c; zCt0CZZ761>(Ug}p;bj5R3Wq*hIzGS(c^8zF*$gwRASnsfjoy*onl%P3Zd{ivOx4Jm z!LjRHX%~7LaP%k;lf|wei9%woa`~l8<3k3cPYVl6�TRo^k1AhW393m3wm}KBi5N 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≤8 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�!h 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νqY{NGn=~OkCd6_N>uw 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 O9%>joC|7&(>i+<Yp7H4b literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Overview_before_release.png b/docs/contribute/general/_assets/Overview_before_release.png new file mode 100644 index 0000000000000000000000000000000000000000..6d665ec20b04fb201d09e9354497ad412b2ad281 GIT binary patch literal 84138 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 Iwd}+G2jVxTqyPW_ literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Release_select_tag.png b/docs/contribute/general/_assets/Release_select_tag.png new file mode 100644 index 0000000000000000000000000000000000000000..6157c5699dc6edf8b0540fa6ef9e25b33f70e516 GIT binary patch literal 79298 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 IW%1^}0Rq~J)&Kwi literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Releases_other_way.png b/docs/contribute/general/_assets/Releases_other_way.png new file mode 100644 index 0000000000000000000000000000000000000000..1fdafcf641edd247c07c31edf47324484dd4d719 GIT binary patch literal 8575 zcmd6NXEdB|v@dBwiV)ETk!aCIkRf`AKBAXk5S>xRXd`O=Nks2uq6>zo6J?lDMk0ER z-bseRV2Iv1{`cMw_tRPTemUoSc-Fg~z4rS&d;QkC_x|m@-w0i8wL3JdG!zsRcQn+M z^(iPQ>n|7W%`2CZhQw5c%Lk>GzM2w6ML!$qa&yg5@s%P4MP=NrQ|s%Oduk7LQ!fe% zMxK8crG`HD-%BCAx5{g81DJz1!rIfGLe10O-rdUy=51+o^YRtWeGO$rLqALM?1hez zW8UW039X-E?z?(AWfjGHKkkG+)=!Qt7sX8FSCSqTkB{Up`+jB_fy#WSjUMawlVWt? zjTLoc$$)~m#<Ss#`3aQ~)`dT`0I03lnryEE(fIb){tK-SkADV@9bmFC`*Q=I?zq=( zF7ADhUo#yr>nX^QpC6mLaO)mnqj;g!%0uzw5s>l)HJqA4GaO8zs|307j-EhIk$ewH zk^2#Qje_UDPQ{)^b0G74qULm_QA(U<sV~z))=N9W*|+iu9g*<$D_7QaPHBP|%5JGY zGh1Q2tK+NkD?KYH<qPgs`^e7DwBkLUpfu*B=ip31%#H7`p;lsT6r%a0gSH-^7O3_R zF7-u;|JnkNS^U&B&PPDLx|&|+)%?vBWtlusaS%oA$5vvt*Gtv-qri}ml?-!a@cbZz zKZ{<HFr-s3y>jDsLim`v7H1+n7ChZ#?r4eL&SIt_42kHSX-W<jdOx7}q}+j8(GGSw zniF_7(*U<?^0r|M2X{>@3vyX=+`pOp8`~HJk2}#Nk1d!$*ayD!z;JQxp;+&p&NO~| zh)t#O-NP6d1UeStIUL!ui9g!y7}B$EMVZ?a37sjQ3_YNX4uRB%t-j20Pl_vf40KDw z!F`0s@&1hmFvN!Wg}=gW+WFHJNBt~{^*2=9_wOOuk$6yC@PQRmIx%002Oy(;O6(^G z7-t0>z^qPoJ8Oyhn9p$22J#`!1(8KP9DsnG6O;C16xYBy=QU>sIeS6mlGC%ZX{!*p z&3r0-abbmT>A~HLt)IW@5NIp;^D6XGa<?$K`GT+%pYm#|{T*OAmRy!nLLxYg3C2Fi zwr@T@xbS#C<hj|Bflrq&JEBO0$Mqxz<=ip7_;MTzyg0&{@9UvYBnLL&VJ0=$vYG9E ztM&ZE29vwZzl&%7%*5qjU&3rI_1a|g*`oph7&22uL)C!W%G#}IS@U9olW}6UltnkD z^PG4l(pSdTxL;(oIfo}Yw#cXfPmh8^=TP4Ri0`Jc?Zj;)ZHWIcNn-AK)s#H9A&&lU z*d`t~dT?~-PvPu?vyL<TL1sY|8&ZS~x8$As2|vb4IyoJ4bF?_$kUHQfJaGR^e2It_ z+&`OT#~h%&rBh6D>WOT}=Nmrxcqd4}lL5En#&eQeNFUll(wBU=dYG{n;A)0vfF_&{ zt4Z#GXD+5Yrd@*6jKW<sOsF{QsbhP>0TCOs(p&cjuoI(ejUi_v+C@4hIO0{AbNt!* zvhmvjthdU*ESS9_b}<Q-b<+Oi;!lH!j)EJq8DYD!nS-w$6`w$p4_io{!ND^E^PWr1 zWi4NHnr45N6j{xaqSFPlsKdU9C>&K9RF@nfB-c9{N8A|%Bmvx#uvi8t-6>%nwuU@h z)e-3qGmQA(Rz<{u6$T?@5EBQ+15>p48UcvRhFzNV+I1JvvvX9CgY`#jU{8PXySMLt zTD>lsk+w#-=0G@}C1Lkl=lgsiYkC#S$J^e&YYP96;>tSDEmsw9DPVrWS2V*c^QK%m zM?qUTXGel(^j5*ATu1R@V;z)r)ZslMb6cC*XxX6I5)afcVgw`Yy|d1k|MWR9>(SpV zaS`*-+R+^4rbxAu2c_V(R{PNemnG6;EX-1Ne>+J#2r0mKd~)|Bw%$y_q@E$;&eBn^ zJ;Rdv>0D^jG_A$?z>f<@OZZ=fV}+?E;|jK}bsN&^_k7pDC7|GVcXg`14SqG96xF>U zexm~=N5=x54;bUGpW2g|j?0pVZ{2ch|2uv1a)XEUz@2YC=x)$iTZGlw$h1PtamX#n z278plhpq_5A0ohcaWf8Ig>((OuTZ2xz4YHFfDRPLz-q_5LM4;*Gg=WKIM}m(Aba@s zVk|fxuW%>KJ@B`yPox4cCH)R>n<=+1B=YXM2~r_&&+3BM7UHJh`POOTN#oga&Y?Cn zw*|Xja*Qp6MkL3lwg;j>Gz)_hwu9$!!w*k^c?e4@mrQy=;3i}{Yi$f~gx>6pgqG^p zVeEHB`m?0ZepJRHDqfQV7W7T_cGso~wX5HES$ZHiLRO}(lj=Ft_Wc~4^CbaV@TVKQ zz>8zRc-3KCY@j=YI2StWYi)PCof5ef13pNsbYxky=c}!_0GdfpykDpqw(O<jUoec# zUColu-=>`p3i^QwE~id!*e#yfUW-Cxf_7ax_Ci_5H4&#^$@Je2ANYZLu2KqiHT!jO zvP8_oiz3tD83T@R6vubB%mq(q|8T|Dw(h*O;7!QY*Up(7iXISSj!p4f7@y_WdPK+w za<Ko{rv^KMW%MmeuLx-Hu}QYFpmCCjUscVU-v^Xy2rgXgHpgHa5!Pq}W@<nLMcrk* z;Wx1I*k5r1eCW;ej2ni91Rr+{t^Q3?2wEnTgF7-4e`7Pv_SWPB1P{+Ln279Pp3?om zzeh3RXx0!P`(0#FRy1RlOaM3VxiiLhT7Lc{Dn({s@&~ken8dL_)vExV-a}he)_Gkz zma<RAaTV<awCq#Bz6E}F@B&ofxpQXkYpv{RKsCe532eG0GymG!5Z5uOS^=oCTCbeL z`HDEIh4*Cguf-kUm_qtkG|qU^U@^WM+2RXBAZ8{!Xl_+>?gAHb0=Res2>})<HdU>e z1#PD7l;qiulSvzsBKxmlg;v!I`c0D*t0Ic$ghZ(zDL-;j)A3r|=0O^l_vS|j<;H8& z*jMTh|KoQRpq#xhkx7dZ&LFi+)yM6q+U`@00wl%<(eGL<0G@>6jzadIlfiIO$&&95 z!F-N`aH|>5Mgn=vE_alr!$E)-NB05!G7B7a0U=+0VHWQL-r3m@^iNh%O}3{Eo3NnY zT7QKvwkmZ{aaZr$nI$!xYBU_kwLO6s56WNPo!o;#V3w;2_q~aPEw|Ff;pDaXA^cT4 zBf#-edzv=+rLrO%=Q|y6+=QbyzHo{Ugh`M~)pL3tvedsNi*IIkV>41(cPQ&H=-`=) z(QiIq{(NZ;o;l~jX+M?!eM6m|9{Jg+1g#Xy=t6jRneh3y7Vdv<<pS~v22b7o{HB%2 z&Dh~Mno`+vRapt5ZR4CaOfM6`Z+72J(}eO3Cy-Av!98NtHqy6Klaq!Z_8>ZlBk4$! zlb0Z-Vz=1KHv1it*(Uuw_dQmNKMf~7+Od?!8!$-e)B1n&7PFAyv!LF|wmjwJsQgCS zyRA|GwH)d{;d8~D`K}Hd-Fd&-hfc{4LIYZ=4~zza1*O(Y84tKNG-oofFX1^uSyz*8 z!lfcmOrHwnB%6O@+Kz;yS|3(%<bZs%SDKf#GZG(-2Rey)ww{GI&>!$_=*|>j&9|uF z%bu?|Np#30{i$fu@Hi6_-jpX#?PG%Xv$TkY2M0nMkeOyb8q$;a-te9-z5tS|Xv>2y z`99o1YJAt>%Vtg+)KQKJcPTZZu$gwsMOwF=#Tg4)xO4qzwuA@~1)iKzmq%+j**dS} zFmVr#EKb-jhV#)6@F1^tg<&(FDHj$%)wE=pA|e*mAli4$a>IjBXj%L4B3r{)?n}v) zNwDK`osed+DAr0f)=$+qIKG#j4QX1<sP@R{Q)CUx@U4T72DWZ|(p%94jY*4-1u5UK zLY589q*<!L(Yg?x5)Hn`(xS>)`!j*Xx?&4|z3zn2r}qA3PlvQ7iE*n9X=*`?>nu|f zMQP{_Ec~s%{_QLId?I+C9_jqbekZv4bgNp2TiWa8Fk(D81Y5O@xibGK%};-;v2o|a zV)AEfP5!sjkU-{83pcj=;*M%RQh(In-BIe<r%kPpiccVwGIp)#SQ%h@WP2R_g3}C5 zQ&!yC*3D?BBYJvg1>1|F%&K%<_HiY%l?(d1fp%{QJe<I42Vn_M#cO%q>I9B&abO#u zw3R(i)^wGmf0fZ=m{w6;9}KBe6D<$CWocfv9cwGlhVrxA8qt3gf1CFiFchxU+xrq_ zJONr?6^6X6dh;^GqR3Rgne+}~CDuMn#s&s_YedbLUUCUTQw`O${h=sB<|n?8PY(SP zXUfFl6!7jM^l-R34l%kY+y{y^QzZF7;e|oREqN_Jb>z0Fnoi?NYrI^_U)Jv$*|%8; zrk)NyKbYjx78VIqP0mo{H^mNmRpjhX(a!^ww$oOy4DI});u5!6-6Zgy&-#E?BL<F; zQm<UjMZ<l-0?DAz*N7Qp-Vhk3%8#&5Abfk~05N;Ot<&c|6ssE7v&#hKK;Cuk^$P8< z3@EXbhuRUIEa=N({Ctb=`K@p$L1-4@KL<n|0PfsnT*CGIJStxbZ7ChccJtWETBrv? zK1rlH$jO5RZWr7`mbNsT{e4|InWYtiukXHzo(F!rn7=2>j0U2gL9@U1TYN<d37PsC zi%7Be(}iR;<<6Ad>*xO^Xtyk1D+>ABIIAA`0j?+u5;@|ezU2G;Um+IQ^^iy!eO&zS zRv}U`$jn71=Z{=+t^aqd=EB&^4bM2yY~aWGpZ=J7<kaHJ{FLS<rL6^5(FHMKyBjFs zP03?^#}Z8E@bz}$ZiqRGNnWaYf<JS+<^FMQuu<1>CVxy+%wmwN4Qo3)l2F`M4G#VO zQZg3K|9<ER8g|ib;SRR5saTPmqP__Vc+pfk&0-I3_p8@+FfMh`ehp#VpcV|y6W*Ue z>FPcW@@i}B=j&F0m<H^dHsP0(bFo612vxK%wpC!z=(9zC$+&}dSFP$y2t=<6^HlCl z_u~!hNbP+x_5Zn)r2P_sGtZ+Jx6P8;VU9O8jt5~5?7(3{mpI#+RI{@c&yJewG6vmz z*tZ@u8Yv>*9@)c!Yu?oo0ZKItnWaW>Ab%vqNpMjPO9J1v@CVke&Ubr8TQ}6v?O_>o z%H<jiZ_2tZFeCG3Ch)-ev<*)UC3^9Ow-Zi}zIr+K38?lrh-Oz*9v1~;`U3KOz+7NM zNTD0VMkrii&NQ{!?h{=6+#s)w_|SMPn_9PW7SgPJi|GM}rL}Owt$w9@@QCCsk5qqd zTb<sphsZx0LrWX)Q}}$Aqs*z+%3rC!+Ke?6did(0xZVf&#WP}ZF-|<LtLR!Au~A=+ z#45dP%A*&mG>ni;mwRRVNd4y<HvY#6aQ@@Op+`QpTD?wh9Yq$Rfxrjaw5hm!kLB>e zvXJW<D(_SMX&iEf;<9NJ9GDo9X+4vaa9m?<ONj(Xa<k4KqcF0JL;B~54Np2xM)&Ys zfPG;1z;f!^)ZySCw?ixY6zcDLsS=?ir`rRc*T(OhpDpg2_3bBZKbmINiEA|j!u;zL ztfUJ#&tsHz`pa(G`=P?t^Gg}s?>KX9g{tgmGxNMx0IEoSdn!B)4GfAIHHReDwXk*S z@PAILmV#`h&JiK{5}Qb#eMVG`henrkK7OXb^?3ugh>*xHDjP1kL<1YbkmWU|_QcON z&lS2=O9BAVfWK%fb3JCasDVoxI$1m81b_?kg&Z%Y@4KsIlUoTm&xg9Q&e$=Fj;X@) ziH)L6B}rS{%#`{frpkNacC~3k6x2FHnzy*M74>@q5GyT876GVOvD3s)8d>)~=tj?f ze2M;yFsdK1*Z{Q;bEO5~RTb(;<T(f_{{5lV``d5q432lAdUOC8VcF%<kOXr!+2DbR zQ{{;n+uilVgB~)Hb2tb6`tZxn6=I^ePRd1<P{)cuKTzoTX>yZz@%ei9-#=~QW#fXc z+PoYd2DHnb(F#Ucd9%~Bfa5Qbj{;jqN082GAjUKE^uC^b!*?Jf1}=-g&sYArG{<Xb zxwdn5D6>h$%^@QO&9=v;Uw9Z1WB525spHBi#Ulm`)#EFa5nRZ|J`1nN#4uZoPc59O zenPnU>*@3<4kiTZ?&JxwbolxQuYIs*|M}<Da!lJ+-m9zo%Tmg5qbD}@Y^~o6;j-Cc z96!|B?Gk=t8B`NKQ+H}w97mqtkSTybXDh#|W%zW8qn@V@TZCG&e^5#3A$u*L4&VMx z{^ItCu=8ErI3f=GsG?QN(3o{dvmp|3SCX}OTuOi37n3`JH2$XvJo{B=z-gTy25`Se zY_Il~cbX^)F?-(ObJ?ajJyh<#r_&v$!|5CYhR{Stq)n7*X`I%u#B;X`0z*GXXc!9+ z!o2>mdwLm!lr^-f#DF&8tjEjO^{oZybUL20X}AY2=-<@Rs`6w|0)P!bx-}Ope_3f0 z=dc|pP99!UDd=N^8hHnSm~Qc!U>?&54eQ4QeGk6Em@>BOgLK1|{u&V}54RWyrpzB~ zt3Kyq846mt1=WNDNb4<ff1C&UavD!W+p?lgm~?(j-Q`V)hyp)y8MC2FS32E%-ooY9 z?mfsa7+9_Ov47DYtUpuEm<%(HIB^`f$BU$n0dpJse_@onjuvKoX|@$s*5MfObf`YF zOB|Q>#fQ7iA|l{E;>m`=O!?u}P4XMD$3O!`)ydwO6qPSAsH17Y)|-fZ{OTl(CoE`` z5ZwB|)H@NMo)**nzjoUUYxCw0pR4<&teHIeu;|V<=;9wN=@$4=JT(&?Xls`iY}+IK z$)z^4H!+y~iKAMuR|uJMr-%2455*HsV2UYxvSvB(lXs`^juY<as^bDX^3VE`HCZW( z3sina6g~sN*2d+2<!l~jS?2dw?NjP~X|&Jn$JU)S4U1(-QyAVucJE@#rul{(?G$}p z%R{>+o<0$H=F|n6gHK8{pDCV=<+Eu2b?bzUO4sfI4yHz{a++6<h;zMt*QYV9Ws|=M z3|DktKm^1Ip35(qR<g*lX}s(pvhbY9vHRHrxBGO+&^`;2zV%lbA$N2WpSb{{bi?hQ zk6FW_CxssBH3T>ST^(H7&O6n`CiwTc8F>0K)O=Rp$Cue+1BtOWshvc1WX)>SGR0m$ z8#l3rYEP9=>J>Ts)EnGPB8ZjOxCEE(yj+Zd?J|wJJ&lvFbYlo@s1K6-R_I~U>Z0<? zh)x{Hv^NqVE!@g;FNYzrr<XlcW)GD5;b%L<(mtc|hM0b33k~lN^`=*HL@ExU>7s!Z zGOGju<6tqeRh&}oEO@L^KMIrPH2FN0$K$;GLQx&Sds%qvRQ6N(G}HhDVeGEIDx7Fn zX;Yx0(z?u5YimoHXgWuXN|r!Mt2|HUS)xRS=^Qg$p7KR*as*iXIxE805yvPxBoF{q zdFpewA0y-BzZ$Vv66B1Y%>a+z|MqWKE9HJSD-2SdF%$9^G(3oe*UQ6J;(GFT%p2DR z!FwDi&|?Y4;h&{)E*mUsH!v-)Z*94^w`hNS+vPD;)^r4*!j#SX8*;Q=4d*c;h<S?% z*=+qDjfee^42oft?q3a~L!Jb9$$?_t0e}K<CVwfo^Nlpglre^N24Uu_jv<iaw`zUX z!qBD#cs_b62i^EF%W}N*tXZ*!B-aLcF)lo<@HB)!O7^=`fhJ@%3-jq6Wfe%?ZL>@4 z9NLP4EdiU2qI!<(vz2H~An6UE%1cvf%TN<%SMtyf@G0=8v%T6aiQUw?+aq{6o8Gkg z)s;Uh9C3g<c+U}Oxq6SWRZ6#ao3ko*olf*jqkNRUX<nGU@@)C%6c706kq!vhtV1zm zncRUh7~sKUYr+PW)TP+`RWjxE*(3x`2x6PMTL3d{>YlsNBbYrTjOEvuImD;;OC5+q zQi5CfYpq%MV=uKozGMeh->iWc+=Z-{ms66w%iyZH5!F4T$X5HYsN>ApYwg73Mt8SE zn5(H|;gwACnm&YeVK<><>CziANeE)BVLqLgY(?GgjV4vGHK$^U1ZjO7?^rkf=Sr7q z)?13-Ndh0Xh-RtRY1?DU!}o3Ad4!?S{Ad2@6&ME?L{sw3b{i_K<k%0A(;eNEB#SQ1 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 U?UFA4kD$;{(N?Zddh`B202q~}(EtDd literal 0 HcmV?d00001 diff --git a/docs/contribute/general/_assets/Releases_other_way_button.png b/docs/contribute/general/_assets/Releases_other_way_button.png new file mode 100644 index 0000000000000000000000000000000000000000..8695cf58040a84aa6aa1045d5da57d9ad9910607 GIT binary patch literal 47913 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 GAN~#GYE10_ literal 0 HcmV?d00001 diff --git a/docs/contribute/general/index.rst b/docs/contribute/general/index.rst index 88f1d6896b..ca99824c62 100644 --- a/docs/contribute/general/index.rst +++ b/docs/contribute/general/index.rst @@ -23,3 +23,4 @@ General folder feature_flags contribution_attribution + release_guide diff --git a/docs/contribute/general/release_guide.rst b/docs/contribute/general/release_guide.rst new file mode 100644 index 0000000000..2fc1560057 --- /dev/null +++ b/docs/contribute/general/release_guide.rst @@ -0,0 +1,292 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _module_release_guide: + + +Module Release Guide +==================== + +Overview +-------- + +In order to use different Modules via the Bazel ecosystem, the Modules have to be released and registered in the S-CORE Bazel Registry. +This short guide will show you the steps necessary to create a release and make it available for other Bazel Modules. + +Prerequisites +------------- + +Before starting the release process, ensure you have: + +- Write access to the GitHub repository which contains the to be released Module +- Access & ability to create pr's (via Fork or otherwise) to the `S-CORE Bazel registry repository <https://github.com/eclipse-score/bazel_registry>`_ +- All necessary changes merged into the main branch +- Understanding of semantic versioning principles + +For further and more detailed information take a look at the `Release Management Process <https://eclipse-score.github.io/score/pr-1445/platform_management_plan/release_management.html>`_ + +Module Release Process +---------------------- + +1. Verify Main Branch Status +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Navigate to your GitHub repository and ensure that all wanted changes are merged into the main branch. + + +2. Update MODULE.bazel Version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ensure that the ``MODULE.bazel`` version matches the version you are about to release: + +.. code-block:: python + + module( + name = "your_module_name", + version = "x.y.z", # This should match your release tag + compatibility_level = 0, + ) + +.. important:: + *If the version in the MODULE.bazel is different from the one you want to release, you need to update them to match* + +Follow semantic versioning (SemVer) principles: + +* **MAJOR**: Incremented for incompatible API changes. + +* **MINOR**: Incremented for backward-compatible functionality additions. + +* **PATCH**: Incremented for backward-compatible bug fixes. + +For a more detailed description of when to update which version look at the process `here <https://eclipse-score.github.io/score/pr-1445/platform_management_plan/release_management.html#identification>`_ + +If you have a major version change that **breaks** backwards compatibility, then make sure to also increase the +compatibility level inside the MODULE.bazel file. + +The compatibility level should be the lowest supported major version that this new version is still compatible with. + +3. Create GitHub Release +~~~~~~~~~~~~~~~~~~~~~~~~ + + Create a new release: + +a. Go to the GitHub repository page +b. On the right-hand side, click 'Create a new release' + + .. image:: _assets/Github_release_button.png + :width: 800 + :alt: Github Release Button Location + +.. note:: Your Release button might look different + + + .. image:: _assets/Releases_other_way.png + :width: 800 + :alt: Github Release Alternate Look + +**If this is the case, you then can create a new release via this button on the following screen.** + +.. image:: _assets/Releases_other_way_button.png + :width: 800 + :alt: Github Release Alternate Look Page 2 + + +| + +c. Create a release tag + + + +Create a new tag following the format ``vx.y.z`` (e.g., ``v1.2.3``): + +- The tag should match exactly with the version in ``MODULE.bazel`` +- Use the ``v`` prefix for consistency +- Target the main branch + + .. image:: _assets/Release_select_tag.png + :width: 800 + :alt: Tag Selector Location + + .. image:: _assets/Create_tag_on_publish.png + :width: 800 + :alt: Creating Tag On Publish + + +5. Write Release Notes +~~~~~~~~~~~~~~~~~~~~~~ + +Add meaningful release notes that document the changes you made since your last release. + + +You can use the generate release notes button to get a good starting point. + +.. image:: _assets/Generate_release_notes_button.png + :width: 400 + :alt: Generate Release Notes Button + + +This then will give you something similar to this: + +.. image:: _assets/Generated_release_notes.png + :width: 400 + :alt: Generated Release Notes + + +6. Set Pre-release Status (if applicable) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Ensure all entered information is correct before you release. Check the pre-release box if necessary + + .. image:: _assets/Overview_before_release.png + :width: 800 + :alt: Github Repository Overview + +7. Register in Bazel Central Registry +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After publishing the GitHub release in the Module repository, you need to add the Module to the Bazel Central Registry: + +8.1 Copy MODULE.bazel +""""""""""""""""""""" + +Copy the ``MODULE.bazel`` file from your released version to the registry structure: + +.. code-block:: bash + + # Navigate to your local copy of the Bazel Central Registry + cd bazel-central-registry + + # Create the module directory structure if it doesn't exist + mkdir -p modules/your_module_name/x.y.z + + # Copy the MODULE.bazel file + cp /path/to/your/project/MODULE.bazel modules/your_module_name/x.y.z/ + +8.2 Calculate Archive Hash +""""""""""""""""""""""""""" + +Calculate the SHA256 hash of the release archive via the following command: + +.. code-block:: bash + + curl -Ls "https://github.com/your_org/your_repo/archive/refs/tags/vx.y.z.tar.gz" | sha256sum | awk '{ print $1 }' | xxd -r -p | base64 | sed 's/^/sha256-/' + + # output will look something like this: + # sha256-s48hf6x3E7XvwgnrDMnKI/97PZju4haQnF0AnPXK9VE= + + + +Here is a convenient function to calculate the hash that you can add to your .bashrc file + + +.. code-block:: bash + + function calcHash() { + curl -Ls "$1" | sha256sum | awk '{ print $1 }' | xxd -r -p | base64 | sed 's/^/sha256-/' + } + + # use it like so: + + calcHash "https://github.com/your_org/your_repo/archive/refs/tags/vx.y.z.tar.gz" + # It will then give you the correct sha you can use for the source.json + # e.g. sha256-s48hf6x3E7XvwgnrDMnKI/97PZju4haQnF0AnPXK9VE= + + +8.3 Create source.json +""""""""""""""""""""""" + +Create a ``source.json`` file in the module version directory: + +.. code-block:: json + :caption: Example source.json file + + { + "integrity": "<calculated_hash>", + "strip_prefix": "your_repo_name-x.y.z", + "url": "https://github.com/your_org/your_repo/archive/refs/tags/vx.y.z.tar.gz" + } + +**Note**: The ``strip_prefix`` should match the top-level directory name in the archive, which is typically ``repository_name-version``. + +9 Add Release to metamodel.json +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Inside `modules/your_module_name/` if not already there create a metamodel.json file, +add your release version to it. + +Here is an example file + +.. code-block:: json + :caption: Example metadata.json file + + { + "homepage": "<the homepage of your repository / documentation>", + "maintainers": [ + { + "name": "<Name>", + "email": "<E-Mail>", + "github": "<Github Username>", + "github_user_id": "<Your GH User ID as NUMBER>" + } + ], + "repository": [ + "github:<your-org>/<your-repo>" + ], + "versions": [ + "0.0.7", + "0.0.8", + "0.1.0" + ], + "yanked_versions": {} + } + + + +10. Verify Module Registration & Create a PR +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Before submitting your changes, verify that the Module is correctly configured: + +.. code-block:: bash + + # In the bazel-central-registry directory + bazel run //tools:verify_modules + +This command will: +- Validate the Module structure +- Check that all files are present and correctly formatted +- Verify that the archive can be downloaded and extracted +- Ensure the Module can be built successfully + +If everything is green, create a PR that includes your changes. + +.. note:: This just does the same test that the CI does. This is a helper to find issues locally before pushing the changes. + + +Your Module Should now Be Available +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once your pull request is merged into the main branch of the Bazel Central Registry, your Module becomes available for use as a dependency in any other Bazel project. + +Users can now add your Module to their ``MODULE.bazel`` file: + +.. code-block:: python + + bazel_dep(name = "your_module_name", version = "x.y.z") + + # example + # bazel_dep(name = "score_process", version = "1.0.4") + + From fd50daaa956b5069b17e155b5dbc2ab5838b02eb Mon Sep 17 00:00:00 2001 From: "markus.schu" <markus.schu@accenture.com> Date: Thu, 17 Jul 2025 10:21:05 +0200 Subject: [PATCH 081/102] update score_tool introduce new doc-as-code version 0.4.4 changed to new doc_tool need for tool verification report updated tool overview list --- MODULE.bazel | 2 +- docs/score_tools/doc_as_code.rst | 28 +++++++++------------------- docs/score_tools/index.rst | 6 +++--- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 6db0f02dc7..f06ed00877 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -90,5 +90,5 @@ bazel_dep(name = "score_cr_checker", version = "0.2.2") bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs -bazel_dep(name = "score_docs_as_code", version = "0.4.3") +bazel_dep(name = "score_docs_as_code", version = "0.4.4") bazel_dep(name = "score_process", version = "1.0.4") diff --git a/docs/score_tools/doc_as_code.rst b/docs/score_tools/doc_as_code.rst index 331816240e..95984fca38 100644 --- a/docs/score_tools/doc_as_code.rst +++ b/docs/score_tools/doc_as_code.rst @@ -12,30 +12,20 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. document:: Doc-as-Code - :id: doc__tool__doc_as_code - :status: draft - :safety: ASIL_B - :security: YES +.. doc_tool:: Doc-as-Code + :id: doc_tool__doc_as_code + :status: evaluated + :version: v0.4.4 + :tcl: LOW + :safety_affected: YES + :security_affected: YES + :realizes: PROCESS_wp__tool_verification_report :tags: tool_management Doc-as-Code Verification Report =============================== - -Identification --------------- -| UID Doc-as-Code -| Version: release-0.2.4 -| Status: evaluated -| Tcl: low -| Safety_affected: yes -| Security_affected: yes - -(todo: discuss to update metamodel with the attributes above, what can be automated?) - - Introduction ------------ @@ -76,7 +66,7 @@ Installation and integration Tool location: -`Release 0.4.2 <https://github.com/eclipse-score/docs-as-code/tree/v0.4.2>`_ +`Release v0.4.4 <https://github.com/eclipse-score/docs-as-code/tree/v0.4.4>`_ How to integrate: diff --git a/docs/score_tools/index.rst b/docs/score_tools/index.rst index 641f6e26e2..66910f802f 100644 --- a/docs/score_tools/index.rst +++ b/docs/score_tools/index.rst @@ -19,11 +19,11 @@ S-CORE Tools Overview .. needtable:: Tools List :tags: tool_management - :filter: "tool_management" in tags and type == "document" and is_external == False + :filter: "tool_management" in tags and type == "doc_tool" and is_external == False :style: table :sort: status - :columns: id as "UID";title as "TITLE";status as "STATUS";safety as "SAFETY" - :colwidths: 30,30,30,30 + :columns: id as "UID";title as "TITLE";version as "VERSION";status as "STATUS";tcl as "TCL";safety_affected as "SAFETY AFFECTED";security_affected as "SECURITY AFFECTED" + :colwidths: 30,30,30,30,30,30,30 .. toctree:: :hidden: From bee81099e81e13ede642ff15e35ec156b7406f05 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Mon, 14 Jul 2025 10:59:33 +0200 Subject: [PATCH 082/102] Align config-mgt-plan with process updates Ref: Resolves #1306 --- .../config_management.rst | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/platform_management_plan/config_management.rst b/docs/platform_management_plan/config_management.rst index 60f8351966..6334dd191f 100644 --- a/docs/platform_management_plan/config_management.rst +++ b/docs/platform_management_plan/config_management.rst @@ -63,8 +63,9 @@ I.e. in Concept Phase, Development Phase and Maintenance. Identification and Properties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Each work product is identified by its sphinx-needs Id, this includes documents identified as such (see project documents list in :need:`doc__documentation_mgt_plan`). -Ids are checked for uniqueness, see <link PROCESS_gd_req__configuration__UID when merged>. +Each work product is identified by its sphinx-needs Id, this includes documents identified as such (by the document header as defined in :need:`PROCESS_gd_temp__documentation`). +The complete list of project documents is defined in the :need:`doc__documentation_mgt_plan`. +Ids are checked for uniqueness, see :need:`PROCESS_gd_req__configuration_uid`. sphinx-needs is also used to document the work products properties/attributes defined in the process area descriptions. The work products are stored in text or code files (these are identified by their filenames) within GitHub repositories. There is one `platform repository <https://GitHub.com/eclipse-score/score/>`_ and one repository for each module. @@ -100,19 +101,19 @@ which are after their acceptance merged by the :need:`Committer <PROCESS_rl__com All modifications (differences between before and after) are documented in the pull-requests and are the main input to the pull-request reviews. See also :need:`doc__platform_change_management_plan`. -For other artefacts modifications are controlled by the bazel build files which are also under configuration control. +For tool/binaries modifications (version changes) are controlled by the bazel build files. These build files, like other files, are also maintained in GitHub. Branches and Baselines ^^^^^^^^^^^^^^^^^^^^^^ -Git defines branches as a means of parallel development. In the S-CORE project the following types of branches will be used: +Branches are used as a means of parallel development. In the S-CORE project the following types of branches will be used: * local branches - created from "remote" branches, in these the development of the contributors takes place, no restriction on naming. * main branch - a "remote" branch (named "main") which contains all the latest file versions checked by CI, reviewed, accepted and merged. * release branch - a "remote" branch derived from main branch which is used to prepare a release, no functional code changes are allowed, only bug fixes and verification based improvements. - Only the technical lead is allowed to approve a merge into a release branch. The branch name is "release-<MAJOR_version>.<MINOR_version> + Only the technical lead is allowed to approve a merge into a release branch. The branch name is given as defined in :need:`PROCESS_doc_concept__rel__process`. The "remote" branch is not "local" to the developer but resides on the "remote" GitHub server. @@ -144,10 +145,11 @@ Status and Reporting Work products defined in our proceses have "status" attributes. These are used to communicate to all the stakeholders. The main communication means is a document list containing all documents including their status. -This list is typically part of the Documentation Management Plan :need:`doc__documentation_mgt_plan` as part of the Platform Management Plan, +This list is part of the Documentation Management Plan :need:`doc__documentation_mgt_plan` as part of the Platform Management Plan, as defined in :need:`PROCESS_gd_guidl__documentation`. Completeness of the configuration items (within a baseline) is checked at least for every release against the list of planned documents, which is also part of the Documentation Management Plan. + Note that work products consisting of several elements (documented as needs) will be collected in one file which will form a document (e.g. there will be a document (doc__*) "feature xy requirements" and in it all the feature's requirements(feat_req__*)). This applies to requirements, architeture, detailed design and safety analysis. @@ -163,9 +165,13 @@ Configuration Management Tooling Almost all requirements of the standards towards configuration management can be covered by standard versioning tooling of the Eclipse Foundation and of the S-CORE project -("structured text" identification of work products). +("Docs-as-Code" identification of work products). The respective tools used in the project are: -* versioning: GitHub -* structured text: sphinx-needs -* CI build: Bazel +* versioning tool: GitHub +* "Docs-as-Code" tool: sphinx-needs +* CI build tool: Bazel + +Note 1: A versioning tool covers part of configuration management but not all (namely: storage, retrieval, control and modification, branching and baselining). + +Note 2: A "Docs-as-Code" tool is used to identify, attribute and link parts of text files and generate human and machine readable documentation. From da6e681d7166024bda0e704f4c4bc21db98fcbd6 Mon Sep 17 00:00:00 2001 From: aschemmel-git <alexander.schemmel@bmw.de> Date: Fri, 18 Jul 2025 14:32:21 +0200 Subject: [PATCH 083/102] Tailor item work product Ref: Resolves #1448 --- docs/platform_management_plan/safety_management.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/platform_management_plan/safety_management.rst b/docs/platform_management_plan/safety_management.rst index 89c433c778..cfdd6d8e43 100644 --- a/docs/platform_management_plan/safety_management.rst +++ b/docs/platform_management_plan/safety_management.rst @@ -122,6 +122,8 @@ The following ISO 26262 defined safety work products are not relevant for the S Expectations towards the HW/Environment are covered by AoUs. Additionally S-CORE only provides reference HW integration, so every user of the platform would have to redo the effort anyway: :need:`PROCESS_std_wp__iso26262__software_652` +* Because the SW platform is not an safety item but an element: :need:`PROCESS_std_wp__iso26262__management_651` + But also some activities based on requirements defining what has to be done to create a workproduct which is in scope of the S-CORE platform are tailored: * Because those are not relevant for ASIL_B: :need:`PROCESS_std_req__iso26262__system_6423`, From 33892a5a29511a5a7eadf3daf04ee6e2a8060bdd Mon Sep 17 00:00:00 2001 From: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> Date: Mon, 21 Jul 2025 10:17:52 +0300 Subject: [PATCH 084/102] infra: Switch docs build to incremental (#1437) With the update of docs-as-code to 0.4.3, incremental build is required. Signed-off-by: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> --- .github/actions/deploy-versioned-pages/action.yml | 2 +- .github/workflows/docs.yml | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/actions/deploy-versioned-pages/action.yml b/.github/actions/deploy-versioned-pages/action.yml index 97c8fb431f..f474e8b049 100644 --- a/.github/actions/deploy-versioned-pages/action.yml +++ b/.github/actions/deploy-versioned-pages/action.yml @@ -123,5 +123,5 @@ runs: with: issue-number: ${{github.event.pull_request.number}} body: | - The created documentation from the pull request is available at: [docu-html](https://eclipse-score.github.io/score/${{steps.calc.outputs.target_folder}}) + The created documentation from the pull request is available at: [docu-html](https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/${{steps.calc.outputs.target_folder}}/) reactions: rocket diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5b91709fa7..21b9c641d6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -55,7 +55,8 @@ jobs: run: sudo apt update && sudo apt install -y graphviz - name: Build documentation run: | - bazel build //docs:github_pages__release && cp bazel-bin/docs/github_pages__release.tar . + bazel run //docs:incremental_release -- --github_user=${{ github.repository_owner }} --github_repo=${{ github.event.repository.name }} + tar -cf github-pages.tar _build # ------------------------------------------------------------------------------ # Generate a unique artifact name to ensure proper tracking in all scenarios # ------------------------------------------------------------------------------ @@ -69,7 +70,7 @@ jobs: uses: actions/upload-artifact@v4.4.0 with: name: github-pages-${{ github.event.pull_request.head.sha || github.sha }} - path: github_pages__release.tar + path: github-pages.tar retention-days: 1 if-no-files-found: error @@ -106,10 +107,10 @@ jobs: name: github-pages-${{ github.event.pull_request.head.sha || github.sha }} - name: Untar documentation artifact - run: mkdir -p extracted_docs && tar -xf github_pages__release.tar -C extracted_docs + run: mkdir -p extracted_docs && tar -xf github-pages.tar -C extracted_docs - name: Deploy 🚀 id: pages-deployment uses: ./.github/actions/deploy-versioned-pages with: - source_folder: extracted_docs/html + source_folder: extracted_docs/_build From 9a54aae4f42a0f2933c24459b544628746435001 Mon Sep 17 00:00:00 2001 From: Armin Bartsch <armin.bartsch@accenture.com> Date: Thu, 15 May 2025 12:22:43 +0200 Subject: [PATCH 085/102] Added FEO feature architecture Change-Id: I02acda06b10a14fdb88815f016459f40c97cc90b --- .../feo/architecture/_assets/dyn_arch.puml | 66 ++++++++ .../feo/architecture/_assets/stat_arch.puml | 72 ++++++++ .../feo/architecture/feature_architecture.rst | 158 ++++++++++++++++++ docs/features/frameworks/feo/index.rst | 1 + 4 files changed, 297 insertions(+) create mode 100644 docs/features/frameworks/feo/architecture/_assets/dyn_arch.puml create mode 100644 docs/features/frameworks/feo/architecture/_assets/stat_arch.puml create mode 100644 docs/features/frameworks/feo/architecture/feature_architecture.rst diff --git a/docs/features/frameworks/feo/architecture/_assets/dyn_arch.puml b/docs/features/frameworks/feo/architecture/_assets/dyn_arch.puml new file mode 100644 index 0000000000..9f99416348 --- /dev/null +++ b/docs/features/frameworks/feo/architecture/_assets/dyn_arch.puml @@ -0,0 +1,66 @@ +/' + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* +'/ + +participant "Lifecycle Manager" as lifecycle + +participant "User Application" as application + +participant feo #C0F0F0 + +participant communication +participant "logging/tracing" as logtrace +participant time +participant "Health Manager" as health + +lifecycle -> application: startup\nprimary process +lifecycle -> application: startup\nsecondary processes +activate application + +application -> feo: create\nprimary\nagent +activate feo + +application -> feo: create\nsecondary\nagents + +feo -> feo: init activities + +group running until term signal + +feo -> communication: send signal +feo <- communication: forward signal + +feo -> logtrace: log or trace events + +feo -> communication: publish data + +feo -> communication: read data +feo <-- communication: data + +feo -> time: read clock +feo <-- time: time info + +feo -> health: report health status + +alt end of life cycle +lifecycle -> application: signal termination +end + +end group + +feo -> feo: shutdown activities + +feo --> application +deactivate feo + +deactivate application diff --git a/docs/features/frameworks/feo/architecture/_assets/stat_arch.puml b/docs/features/frameworks/feo/architecture/_assets/stat_arch.puml new file mode 100644 index 0000000000..1455a17224 --- /dev/null +++ b/docs/features/frameworks/feo/architecture/_assets/stat_arch.puml @@ -0,0 +1,72 @@ +/' + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* +'/ +allowmixing + + +frame "User Application" as application { + agent "Primary Process" as PP + agent "Secondary Processes\n(optional)" as SP +} + +component "Lifecycle Manager" as life_mgr +component "Health Manager" as health_mgr + +component "communication" as com_mgr +component "logging/\ntracing" as log_trace_mgr +component "time" as time_mgr + +frame "feo" as feo { + component "feo_com" + component "feo_log" + component "feo_time" + component "feo_tracing" +} + +interface "Activity" as activity { +} +interface "Primary Agent" as primary +interface "Secondary Agent" as secondary + +interface "Health" as health +interface "Lifecycle Listener" as lifecycle + +interface "mw::com" as mw_com +interface "logging" as logging +interface "tracing" as tracing +interface "time" as time + +health_mgr -u-|> health: impl + +com_mgr -u-|> mw_com: impl +log_trace_mgr -u-|> logging: impl +log_trace_mgr -u-|> tracing: impl +time_mgr -u-|> time: impl + +feo -u-|> primary: impl +feo -u-|> secondary: impl +feo -u-|> activity: impl +feo -u-|> lifecycle: impl + +feo -d-> health: use +feo -d-> mw_com: use +feo -d-> logging: use +feo -d-> tracing: use +feo -d-> time: use + +application -d-> activity: use +application -d-> secondary: use +application -d-> primary: use + +life_mgr --> lifecycle: use diff --git a/docs/features/frameworks/feo/architecture/feature_architecture.rst b/docs/features/frameworks/feo/architecture/feature_architecture.rst new file mode 100644 index 0000000000..a9de2b0882 --- /dev/null +++ b/docs/features/frameworks/feo/architecture/feature_architecture.rst @@ -0,0 +1,158 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Feature Architecture: FEO +========================= + +Overview +-------- +The current implementation of the feature "FEO" (Fixed Execution Order Framework) consists of a main +component and a set of auxiliary components that will be either replaced by or turned into +wrappers to components from other S-CORE features. In the latter case, these wrappers will possibly +become sub-components of the main component. + +Description +----------- + +Feature Components +****************** + +* feo: The main component + +* feo-com: Interface to inter-activity data communication + + Will be replaced by or become a wrapper of the interface `mw::com` provided by the feature + "Communication". + +* feo-log: Logging macros (Rust and C++) and logger implementation + + Consists of the following sub-components: + - feo-log: Logging macros (Rust and C++) + - feo-logger: Logger implementation (Rust and C++) + + Will be replaced by or become a wrapper of an interface provided by the feature "Logging". + +* feo-time: Interface to system clocks + + Will be replaced by or become a wrapper of an interface provided by the feature "Time". + +* feo-tracing: Subscriber for Rust tracing API + + Will be replaced by or become a wrapper of an interface provided by the feature "Logging". + + +Utility and Example Applications +******************************** + +* feo-tracer: A simple tracing daemon receiving trace messages from all feo agents + + Consists of the following sub-components: + - feo-tracer: Tracing daemon + - perfetto-model: Support for the Perfetto trace file format + + Will be replaced by an alternative solution provided by the feature "Tracing". + +* logd: A simple logging daemon receiving log output from all feo agents + + Will be replaced by an alternative solution provided by the feature "Logging". + +* mini-adas: Example of a minimal dummy ADAS activity set + +* cycle-benchmark: A simple configurable benchmarking application to measure the FEO cycle time + + +Rationale Behind Architecture Decomposition +******************************************* + +The feature has been split into a main component, auxiliary components as well as utility and +example applications. The main component implements the functionality that is expected to +be required by most systems making use of FEO. Auxiliary components are parts of the code +that are likely to be replaced by components from other features in the future. They have been +split according to their functionalities. Utility applications are optional +pieces of software that can be run to test or demonstrate the feature functionality but are not +expected to be used directly in a productive system. They may become obsolete in future. + + +Static Architecture +------------------- + +.. feat_arc_sta:: Static Architecture + :id: feat_arc_sta__feo__main + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__feo__application, feat_req__feo__activity, feat_req__feo__task_chain, feat_req__feo__agent + :includes: logic_arc_int__feo__activity, logic_arc_int__feo__prim_agent, logic_arc_int__feo__sec_agent, logic_arc_int__feo__lifecycle + + .. uml:: _assets/stat_arch.puml + :scale: 50 + :align: center + + +Dynamic Architecture +-------------------- + +.. feat_arc_dyn:: Dynamic Architecture + :id: feat_arc_dyn__feo__main + :security: YES + :safety: ASIL_B + :fulfils: feat_req__feo__application, feat_req__feo__activity, feat_req__feo__task_chain, feat_req__feo__agent + :status: valid + + .. uml:: _assets/dyn_arch.puml + :scale: 50 + :align: center + + +Logical Interfaces +------------------ + +.. logic_arc_int:: Activity + :id: logic_arc_int__feo__activity + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__feo__application, feat_req__feo__activity + + See static architecture. + + +.. logic_arc_int:: Primary Agent + :id: logic_arc_int__feo__prim_agent + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__feo__application, feat_req__feo__activity, feat_req__feo__task_chain, feat_req__feo__agent + + See static architecture. + + +.. logic_arc_int:: Secondary Agent + :id: logic_arc_int__feo__sec_agent + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__feo__application, feat_req__feo__activity, feat_req__feo__task_chain, feat_req__feo__agent + + See static architecture. + + +.. logic_arc_int:: Lifecycle Listener + :id: logic_arc_int__feo__lifecycle + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: feat_req__feo__application_lifecycle + + See static architecture. diff --git a/docs/features/frameworks/feo/index.rst b/docs/features/frameworks/feo/index.rst index 80b7d47100..e8fc8d66d9 100644 --- a/docs/features/frameworks/feo/index.rst +++ b/docs/features/frameworks/feo/index.rst @@ -28,6 +28,7 @@ and :need:`Feature Request Template <PROCESS_gd_temp__change__feature_request>`. :hidden: requirements/index.rst + architecture/feature_architecture Feature flag ============ From 3ef33bcb4724cace0beded4e6a1ec7de948100cf Mon Sep 17 00:00:00 2001 From: Armin Bartsch <armin.bartsch@accenture.com> Date: Mon, 2 Jun 2025 20:49:23 +0200 Subject: [PATCH 086/102] Adding FEO component architecture Change-Id: Icc7805259722e7313cbb239f70a58ae9ad6dd210 --- .../docs/architecture/_assets/act_chain.puml | 31 ++++ .../docs/architecture/_assets/dyn_arch.puml | 155 ++++++++++++++++++ .../docs/architecture/_assets/stat_arch.puml | 83 ++++++++++ .../architecture/component_architecture.rst | 144 ++++++++++++++++ .../feo/modules/feo/feo/docs/index.rst | 1 + 5 files changed, 414 insertions(+) create mode 100644 docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml create mode 100644 docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml create mode 100644 docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml create mode 100644 docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml new file mode 100644 index 0000000000..84dc9c64f8 --- /dev/null +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml @@ -0,0 +1,31 @@ +/' + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* +'/ + +hide empty description + +state "UserActivity 1" as a1 +state "UserActivity 2" as a2 +state "UserActivity 3" as a3 +state "UserActivity 4" as a4 + +a1: Primary Process +a2: Secondary Process 1 +a3: Secondary Process 1 +a4: Secondary Process 2 + +a3 --> a1 +a3 --> a4 +a1 --> a2 +a4 --> a2 \ No newline at end of file diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml new file mode 100644 index 0000000000..9fa58b1e89 --- /dev/null +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml @@ -0,0 +1,155 @@ +/' + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* +'/ + +box "Primary Process" #E0E0E0 +participant "Primary Agent" as prim +participant "Scheduler" as scheduler +participant "UserActivity 1" as activity_1 +end box + +box "Secondary Process 1" #F0F0F0 +participant "Secondary Agent 1" as sec_1 +participant "UserActivity 2" as activity_2 +participant "UserActivity 3" as activity_3 +end box + +box "Secondary Process 2" #F0F0F0 +participant "Secondary Agent 2" as sec_2 +participant "UserActivity 4" as activity_4 +end box + +== Process Startup == + +prim -> prim: create \nworker threads +sec_1 -> sec_1: create \nworker threads +sec_2 -> sec_2: create \nworker threads + +sec_1 -> prim: connect +sec_2 -> prim: connect + + +prim -> scheduler: sync_remotes() +activate scheduler + +scheduler -> sec_1: sync +scheduler -> sec_2: sync +sec_1 -> sec_1: sync +sec_2 -> sec_2: sync +sec_1 --> scheduler: ready +sec_2 --> scheduler: ready + +scheduler --> prim: ok +deactivate scheduler + + +== Activity Init == + +note over scheduler, activity_4 +Call each activity's init() method exactly once in an arbitrary order. +end note + +prim -> scheduler: run() +activate scheduler + +scheduler -> activity_1: init() +activity_1 -> activity_1: init +activity_1 --> scheduler: ready + +scheduler -> sec_1: init(a2) +sec_1 -> activity_2: init() +activity_2 -> activity_2: init +activity_2 --> sec_1: ready +sec_1 --> scheduler: ready(a2) + +scheduler -> sec_1: init(a3) +sec_1 -> activity_3: init() +activity_3 -> activity_3: init +activity_3 --> sec_1: ready +sec_1 --> scheduler: ready(a3) + +scheduler -> sec_2: init(a4) +sec_2 -> activity_4: init() +activity_4 -> activity_4: init +activity_4 --> sec_2: ready +sec_2 --> scheduler: ready(a4) + +== Main Loop == + +loop break on termination signal to Primary Process + +note over scheduler, activity_4 +Call each activity's step() method in the order defined by the activity graph. +end note + +scheduler -> sec_1: step(a3) +note left: Step a3 first +sec_1 -> activity_3: step() +activity_3 --> sec_1: ready +sec_1 --> scheduler: ready(a3) + +scheduler -> sec_2: step(a4) +note left: Step a1 and a4\nin parallel, but\nafter end of a3 +sec_2 -> activity_4: step() +scheduler -> activity_1: step() +activity_1 --> scheduler: ready +activity_4 --> sec_2: ready +sec_2 --> scheduler: ready(a4) + +scheduler -> sec_1: step(a2) +note left: Step a2 after\nend of a1 and a4 +sec_1 -> activity_2: step() +activity_2 --> sec_1: ready +sec_1 --> scheduler: ready(a2) + + +hnote over scheduler +sleep until end +of cycle time +end note + +end loop + +== Activity Shutdown == + +note over scheduler, activity_4 +Call each activity's shutdown() method exactly once in an arbitrary order. +end note + +scheduler -> activity_1: shutdown() +activity_1 -> activity_1: shutdown +activity_1 --> scheduler: ready + +scheduler -> sec_1: shutdown(a2) +sec_1 -> activity_2: shutdown() +activity_2 -> activity_2: shutdown +activity_2 --> sec_1: ready +sec_1 --> scheduler: ready(a2) + +scheduler -> sec_1: shutdown(a3) +sec_1 -> activity_3: shutdown() +activity_3 -> activity_3: shutdown +activity_3 --> sec_1: ready +sec_1 --> scheduler: ready(a3) + +scheduler -> sec_2: shutdown(a4) +sec_2 -> activity_4: shutdown() +activity_4 -> activity_4: shutdown +activity_4 --> sec_2: ready +sec_2 --> scheduler: ready(a4) + +scheduler --> prim: ok + +deactivate scheduler + diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml new file mode 100644 index 0000000000..9cd295eba0 --- /dev/null +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml @@ -0,0 +1,83 @@ +/' + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* +'/ +allowmixing + +package FEO <<feature>> as feat_feo { + + struct "feo::agent::Primary" as feo_primary { + + new(config: PrimaryConfig) -> Self + + run(&mut self) -> Result + } + + struct "feo::agent::Secondary" as feo_secondary { + + new(config: SecondaryConfig) -> Self + + fn run(self) + } + + struct "feo::agent::PrimaryConfig" as feo_primary_config { + + cycle_time : Duration + + activity_dependencies : HashMap<ActivityId, Vec<ActivityId>> + + recorder_ids : Vec<AgentId> + {field} + worker_assignments : Vec<(WorkerId, Vec<ActivityIdAndBuilder>)> + + timeout : Duration + + endpoint : NodeAddress, + } + + struct "feo::agent::SecondaryConfig" as feo_secondary_config { + + id: AgentId + {field} + worker_assignments: Vec<(WorkerId, Vec<ActivityIdAndBuilder>)> + + timeout: Duration, + + endpoint: NodeAddress, + } + + struct "feo::scheduler::Scheduler" as feo_scheduler { + + new(...) -> Self + + run() + + sync_remotes() -> Result + } + + interface "feo::activity::Activity" as activity { + + init() + + step() + + shutdown() + } + + feo_primary --> activity: use + feo_primary --> feo_scheduler: use + + feo_secondary --> activity: use + +} + +package "User Application" <<application>> as user_application { + + component "Primary Process" as PP + component "Secondary Process" as SP + + struct "UserActivity_1" as user_activity_1 + struct "UserActivity_2" as user_activity_2 + + PP --> user_activity_1 : use + SP --> user_activity_2 : use + + user_activity_1 ..|> activity : impl + user_activity_2 ..|> activity : impl +} + +PP --> feo_primary : use +PP --> feo_primary_config : use +SP --> feo_secondary : use +SP --> feo_secondary_config : use + diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst new file mode 100644 index 0000000000..3f0bc952c4 --- /dev/null +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst @@ -0,0 +1,144 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Component Architecture: feo +=========================== + +Overview +-------- +The current implementation of the feature "FEO" (Fixed Execution Order Framework) consists of a main +component (called "FEO" component) and a set of auxiliary components that will be either replaced by or +turned into wrappers to components from other S-CORE features. In the latter case, these wrappers will +possibly become sub-components of the main component. + +This document describes the architecture of the main component "FEO". + +Description +----------- + +Sub-Components +************** + +The main component "FEO" consists of the following sub-components: + +* feo: Implements activities, threads, agents, and scheduling +* feo-cpp-build: C++ and Rust Code simplifying the integration of C++ components +* feo-cpp-macros: Rust proc-macros simplifying the integration of C++ components. + +Rust requires proc-macros to reside in their own crate, therefore the latter two +sub-components cannot easily be combined into a single one. + + +Rationale Behind Architecture Decomposition +******************************************* + +The main component "FEO" has been split into three sub-components mainly according to usability +considerations and Rust compiler constraints. (Rust proc-macros must reside in their own crate.) + + +Static Architecture +------------------- + +.. comp_arc_sta:: Static Architecture + :id: comp_arc_sta__feo__main + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__application, comp_req__feo__scheduler, comp_req__feo__task_chain, comp_req__feo__agent, comp_req__feo__comp_cfg, comp_req__feo__act_map_cfg + :includes: real_arc_int__feo__primary, real_arc_int__feo__primary_config, real_arc_int__feo__secondary, real_arc_int__feo__secondary_config, real_arc_int__feo__activity + + .. uml:: _assets/stat_arch.puml + :scale: 50 + :align: center + + +Dynamic Architecture +-------------------- + +.. comp_arc_dyn:: Dynamic Architecture + :id: comp_arc_dyn__feo__main + :security: YES + :safety: ASIL_B + :fulfils: comp_req__feo__application, comp_req__feo__application_lifecycle, comp_req__feo__scheduler, comp_req__feo__task_chain, comp_req__feo__agent, comp_req__feo__activity_init, comp_req__feo__activitiy_step, comp_req__feo__activity_shutdown + :status: valid + + The actual dynamic call sequence during the execution of a FEO application depends on the distribution + of activities to processes as well as on the activity dependency graph defining the task chain. + As an example, we consider the simple task chain and process distribution depicted in the following diagram + + .. uml:: _assets/act_chain.puml + + For this task chain, a possible call sequence is shown below. + + .. uml:: _assets/dyn_arch.puml + :scale: 50 + :align: center + + +Interfaces +------------------ + +.. real_arc_int:: feo::agent::PrimaryConfig + :id: real_arc_int__feo__primary_config + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__application, comp_req__feo__task_chain, comp_req__feo__comp_cfg, comp_req__feo__act_map_cfg + :language: rust + + See static architecture. + + +.. real_arc_int:: feo::agent::Primary + :id: real_arc_int__feo__primary + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__application, comp_req__feo__task_chain, comp_req__feo__comp_cfg, comp_req__feo__act_map_cfg + :language: rust + + See static architecture. + + +.. real_arc_int:: feo::agent::SecondaryConfig + :id: real_arc_int__feo__secondary_config + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__application, comp_req__feo__task_chain, comp_req__feo__comp_cfg, comp_req__feo__act_map_cfg + :language: rust + + See static architecture. + + +.. real_arc_int:: feo::agent::Secondary + :id: real_arc_int__feo__secondary + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__application, comp_req__feo__task_chain, comp_req__feo__comp_cfg, comp_req__feo__act_map_cfg + :language: rust + + See static architecture. + + +.. real_arc_int:: feo::activity::Activity + :id: real_arc_int__feo__activity + :security: YES + :safety: ASIL_B + :status: valid + :fulfils: comp_req__feo__activity + :language: rust + + See static architecture. diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst b/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst index 24c08a7459..408723fec9 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst @@ -21,4 +21,5 @@ Component Documentation: feo .. toctree:: :maxdepth: 1 + architecture/component_architecture requirements/component_requirements From 5e4209a8e7495e907a80622756a60b7cdb5fa313 Mon Sep 17 00:00:00 2001 From: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> Date: Mon, 21 Jul 2025 17:19:17 +0300 Subject: [PATCH 087/102] bazel: Add cli help (#1435) New feature that adds description of some useful score bazel targets. Signed-off-by: Nicolae Dicu <nicolae.dicu.ext@qorix.ai> --- BUILD | 14 ++++++++++++++ MODULE.bazel | 11 +++++++++-- README.md | 3 +++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/BUILD b/BUILD index 2f5b0b5375..07e273b95a 100644 --- a/BUILD +++ b/BUILD @@ -11,17 +11,26 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +load("@score_cli_helper//:cli_helper.bzl", "cli_helper") load("@score_cr_checker//:cr_checker.bzl", "copyright_checker") load("@score_starpls_lsp//:starpls.bzl", "setup_starpls") test_suite( name = "format.check", + tags = [ + "cli_help=Check formatting:\n" + + "bazel test //:format.check", + ], tests = ["//tools/format:format.check"], ) alias( name = "format.fix", actual = "//tools/format:format.fix", + tags = [ + "cli_help=Fix formatting:\n" + + "bazel run //:format.fix", + ], ) copyright_checker( @@ -38,6 +47,11 @@ copyright_checker( visibility = ["//visibility:public"], ) +cli_helper( + name = "cli-help", + visibility = ["//visibility:public"], +) + exports_files([ "MODULE.bazel", "BUILD", diff --git a/MODULE.bazel b/MODULE.bazel index f06ed00877..d50218fba7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -73,14 +73,21 @@ bazel_dep(name = "rules_java", version = "8.11.0") # ############################################################################### -bazel_dep(name = "score_python_basics", version = "0.3.2") +bazel_dep(name = "score_python_basics", version = "0.3.3") ############################################################################### # # Checker rule for CopyRight checks/fixes # ############################################################################### -bazel_dep(name = "score_cr_checker", version = "0.2.2") +bazel_dep(name = "score_cr_checker", version = "0.3.1") + +############################################################################### +# +# CLI helper rule for CLI help +# +############################################################################### +bazel_dep(name = "score_cli_helper", version = "0.1.1") ############################################################################### # diff --git a/README.md b/README.md index fe4f3d2c77..adfb454304 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Follow [instructions](https://eclipse-score.github.io/score/main/contribute/deve Some important commands to get you started: ```sh +# Display useful bazel commands +bazel run //:help + # Check formatting bazel test //:format.check From 906114ba28a59d608a13d33183c9bcd2f3182891 Mon Sep 17 00:00:00 2001 From: qor-lb <lars.bauhofer@qorix.ai> Date: Thu, 3 Apr 2025 16:54:50 +0200 Subject: [PATCH 088/102] docs: added orchestration feature request closes: #273 --- docs/features/orchestration/index.rst | 392 +++++++++++++++++++ docs/features/orchestration/requirements.rst | 383 ++++++++++++++++++ 2 files changed, 775 insertions(+) create mode 100644 docs/features/orchestration/index.rst create mode 100644 docs/features/orchestration/requirements.rst diff --git a/docs/features/orchestration/index.rst b/docs/features/orchestration/index.rst new file mode 100644 index 0000000000..68cee6a645 --- /dev/null +++ b/docs/features/orchestration/index.rst @@ -0,0 +1,392 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _orchestration_feature: + +Orchestration +############# + +.. document:: Orchestration + :id: doc__orchestration + :status: valid + :safety: ASIL_B + :realizes: wp__feat_request + :tags: feature_request, change_management, orchestration + + +.. toctree:: + :hidden: + + requirements.rst + + +Feature flag +============ + +To activate this feature, use the following feature flag: + +``experimental_orchestration`` + + +Abstract +======== + +This feature proposes two frameworks, the Executor and the Orchestrator, to support deterministic, scalable, and maintainable execution of mixed-criticality software applications. The Executor provides cooperative user-space multitasking using a configurable thread pool, reducing overhead and improving control over scheduling behavior without relying on one-thread-per-task models. It supports safety-critical preemptive tasks, dedicated threads for blocking operations, and structured observability. + +The Orchestrator complements this by offering a declarative model to define cause-effect chains, timing constraints, and fault handling logic. Programs are structured as runtime-static graphs mapped to Executors, enabling clear separation between application logic and deployment configuration. Integration workflows distinguish responsibilities between application developers and system integrators, supporting both unified and distributed development scenarios. + +Together, these frameworks reduce integration effort, improve timing predictability, and allow validation of cross-component timing chains. Observability hooks enable correlation between application-level logic and OS-level scheduling. This design avoids runtime surprises due to implicit assumptions in thread usage and timing behavior, supporting more robust system integration in automotive and safety-critical environments. + + + +Motivation +========== + +Application Behavior in Mixed-Criticality Domains +------------------------------------------------- + +In software systems for domains like ADAS and automated driving, applications frequently follow periodic cause-effect structures. A typical example includes a camera providing images at 30 frames per second, with each frame triggering object detection, which feeds into a fusion module to compute a new trajectory. This repeating, sensor-driven processing cycle defines how most software on the mixed-criticality processor domain is organized. The structure remains valid even when offloading is involved, such as using GPUs or NPUs for computation. + +This execution model already shaped software development in microcontroller environments (e.g., Classic AUTOSAR), and continues to apply to more powerful systems. What changes is the complexity of algorithms and the compute and communication cost between them. But the underlying pattern, periodic execution triggered by external or internal stimuli, remains relevant and useful. + +The goal is to support this type of application logic natively and systematically across different runtime environments without requiring developers to micromanage scheduling behavior or resource usage. + +Integration Complexity Due to OS-Level Thread Management +-------------------------------------------------------- + +In today's systems, application development is often distributed across teams or organizations. These teams typically focus on their own application logic and do not have full visibility into the target deployment. However, current APIs often expect applications to manage thread lifecycles directly, including thread creation, priorities, and affinities, as is the case in Adaptive AUTOSAR. This results in applications being tightly coupled to assumptions about system resources and execution environments. + +Once the application is deployed, these assumptions often break. A typical integration issue occurs when an application shows correct timing on the development system but exhibits unexpected behavior on the actual target. This leads to repeated coordination loops between developers and integrators, adjusting priorities and affinities manually. As a result, the deployment becomes brittle and tightly bound to the specific configuration of the system, making re-use and scalability difficult. + +This issue is amplified in mixed-criticality environments, where scheduling decisions have direct safety implications. Lower-criticality software must not interfere with the timing of high-criticality components. This makes unmanaged threading even more problematic. + +Timing Awareness and Predictability in Application Logic +-------------------------------------------------------- + +In current systems, timing supervision and error handling are often implemented in separate, system-level components like health monitors. This leads to low cohesion: timing constraints and critical behavior are managed far from the application logic that they affect. It also makes it difficult to validate cause-effect chains that span multiple applications or components. + +A more robust design would allow timing monitors and error paths to be expressed alongside the application logic they supervise. This would improve local reasoning, simplify debugging, and support more deterministic system behavior, especially when coordinating multiple applications with timing dependencies. + +Concurrency Overhead in Service Infrastructure +---------------------------------------------- + +The system must also support platform services such as diagnostics, configuration management, health supervision, and communication gateways. In existing stacks, these services often run one thread per client, leading to rapid thread growth. For instance, 15 services accessed by 150 applications would result in over 2,000 threads. This can create significant performance problems, including increased context-switching, memory pressure, and degraded throughput. + +The platform must support a concurrency model that can scale to such numbers without relying on a one-thread-per-task model. Reducing thread count while preserving concurrency is essential, both for platform services and for user-level applications. + +Observability and Validation in Real Deployments +------------------------------------------------ + +To support predictable behavior and real-time debugging, the system must offer visibility into task-level execution and its interaction with the OS scheduler. Developers and integrators need to answer questions such as: When was a specific task scheduled? On which thread? Was a delay caused by CPU starvation or by another blocking task? + +This requires instrumentation that correlates user-space task execution with kernel-level scheduling behavior. Without such observability, it is difficult to validate integration or analyze failures in timing-critical systems. + + + +.. Rationale +.. ========== + + + +Specification +============= + +To address these challenges, this proposal introduces two frameworks: + +1. The **Executor**, which provides cooperative, user-space multitasking on top of a configurable thread pool. +2. The **Orchestrator**, which provides a declarative layer to define execution structures and timing requirements in a way that is independent of the deployment platform. + +Together, these frameworks allow developers to write reusable application logic and enable integrators to manage deployment, scheduling, and timing without modifying the code. + +Executor +-------- + +The Executor framework provides user-space multitasking through cooperative scheduling of tasks over a thread pool. It abstracts OS threads into lightweight tasks, enhancing concurrency without incurring excessive OS-level overhead. The framework addresses scalability, predictable scheduling, and controlled resource allocation in mixed-criticality software systems. + +Task Model +~~~~~~~~~~ + +Tasks are the fundamental concurrency unit managed by the Executor. A task represents a schedulable computation defined through a future-based model. Specifically, a task is an independently executable sequence of computation that progresses cooperatively. Tasks explicitly yield execution at defined points (``await``), allowing controlled switching between tasks without preemption. + +This cooperative scheduling model offers: + +- Reduced overhead and context-switching. +- Improved system scalability due to lightweight task management. + +Cooperative Multitasking +~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, tasks execute cooperatively and must voluntarily yield execution. Tasks explicitly yield at await points or logical suspension points, aligning with models such as Rust's ``async/await`` semantics or C++ coroutines (``co_await``). + +Tasks must avoid blocking or indefinite execution without yielding. Developers are responsible for ensuring tasks are appropriately structured to cooperate with the scheduler. + +Handling Long-Running Tasks +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Long-running tasks, or tasks containing blocking calls, present challenges in cooperative scheduling environments. The Executor framework must provide mechanisms for handling these scenarios effectively: + +- **Guidance on task chunking**: The Executor must provide guidelines for developers to divide long-running operations into smaller, cooperatively yielding segments. This approach aligns with best practices for embedded concurrency patterns, as detailed in the `Ferrous Systems article <https://ferrous-systems.com/blog/embedded-concurrency-patterns/#async--long-running-operations>`_. + +- **Dedicated threading**: For tasks that cannot be chunked easily, such as tasks using third-party libraries with blocking operations, the Executor must support running these tasks on dedicated threads. These dedicated threads are isolated from cooperative tasks, ensuring predictable execution and avoiding interference with the cooperative task scheduling. + +Preemptive Special Tasks +~~~~~~~~~~~~~~~~~~~~~~~~ + +Certain scenarios, particularly safety-critical fault detection or timing monitoring, require tasks that can preempt cooperative tasks. These special tasks are managed separately and guaranteed execution to avoid starvation or blocking. The Executor framework must provide mechanisms to support: + +- Preemptive scheduling of these special tasks. +- Isolation and prioritization of safety-critical tasks distinct from standard cooperative tasks. + +Thread Pool Management +~~~~~~~~~~~~~~~~~~~~~~ + +Tasks run on OS threads managed within statically configured thread pools. Each Executor instance has its own dedicated thread pool with: + +- A fixed number of threads defined at configuration time. +- Identical OS-level thread priority across all threads within the same Executor. +- Optional configuration of thread affinity to specific CPU cores. + +This ensures predictable timing and resource utilization. Thread pools are isolated per Executor instance; threads are not shared among Executors. + +Task Scheduling and Prioritization +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Within an Executor, standard tasks have uniform priority and execute cooperatively without task-level priority distinctions. Task scheduling follows either FIFO or fairness-based ordering within the cooperative scheduling context. + +Preemptive special tasks are managed distinctly and do not compete with cooperative tasks for scheduling. + +Scaling +~~~~~~~ + +Scaling across multiple Executors is achieved through instantiating additional Executor instances rather than dynamically scaling existing thread pools. While each Executor is assigned to a single process, a single process may host multiple Executors to partition workloads or isolate scheduling domains. Each Executor instance is independently configured regarding: + +- Thread pool size +- OS-level priority +- CPU affinity + +This explicit configuration avoids interference across different criticality domains, maintaining determinism and composability in system integration. + +Orchestrator +------------ + +The Orchestrator framework provides a structured, declarative way to define cause-effect chains and timing requirements within software applications. It enables developers to specify control flow, timing constraints, and error handling in a platform-independent manner. The Orchestrator integrates seamlessly with the Executor, clearly separating application logic from deployment and resource management. + +Program Abstraction +~~~~~~~~~~~~~~~~~~~ + +The primary abstraction within the Orchestrator is the **Program**, which represents a runtime-static execution graph. Programs describe computation logic in terms of: + +- Sequential, parallel, or conditional execution flows. +- Loops (bounded iteration or periodic execution). +- Timing contracts, including deadlines and timeouts. +- Trigger conditions via events and cross-program synchronization. +- Fault handling logic, such as fallback paths and retries. + +Program structures are fixed either at compile-time or during startup. While parameters may be reconfigured dynamically, the structural form of a Program remains static. + +Code-First API Design +~~~~~~~~~~~~~~~~~~~~~ + +The Orchestrator employs a code-first API approach rather than a textual DSL or IDL. This ensures: + +- Direct integration with application logic. +- Improved debuggability and flexibility during development. +- Simplified tool support, enabling incremental addition of declarative frontends if needed. + +Execution Model +~~~~~~~~~~~~~~~ + +Each Program is deployed to a single Executor instance. Executors may host multiple Programs to facilitate resource sharing or logical grouping. Programs communicate and synchronize through explicitly defined events. Events serve as triggers or synchronization points and form the interface between individual Programs (potentially shared across Executors and processes). + +Design and Integration Scenarios +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Orchestrator supports flexible development and integration scenarios: + +- **Unified Development Scenario**: A single development team manages the complete cause-effect chain within one Program, explicitly defining all timing constraints and logic. + +- **Distributed Scenario**: Different teams independently develop Programs for separate components. An Integrator combines these Programs into a coordinated *Program-of-Programs* by wiring events and managing global timing constraints and fault containment. + +Timing Semantics +~~~~~~~~~~~~~~~~ + +Timing semantics in the Orchestrator are defined declaratively through three primitives: + +1. **Events**: Trigger execution at defined intervals or upon external stimuli (e.g., sensor inputs). +2. **Logical Delays**: Insert cooperative, non-blocking delays within execution flows (``sleep(duration)``). +3. **Execution Monitors**: Observe and enforce timing constraints, triggering specified error handling paths upon violations. + +This approach enables precise control over timing behaviors without relying on polling or dedicated monitoring threads. + +Special Safety Tasks and Preemption +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Programs may define critical timing or safety measures within the error handling paths, which the Executor ensures to execute preemptively by utilizing the safety tasks introduced above. This guarantees that timing constraints and fault responses execute reliably, even during saturation or task overload conditions. Such preemptive execution is configurable per deployment scenario and activated only when explicitly defined by safety or timing constraints. + +Integration Workflow +~~~~~~~~~~~~~~~~~~~~ + +**Application Developer Responsibilities**: + +- Define Program logic using Orchestrator APIs. +- Declare events for synchronization and triggers. +- Establish timing and error-handling paths. + +**Integrator Responsibilities**: + +- Instantiate and configure Executors (thread count, priority, affinity, criticality). +- Map Programs explicitly to Executors. +- Wire events between Programs and external sources. +- Optionally integrate multiple Programs into coherent cause-effect chains (*Program-of-Programs*). + +Anticipated Tooling (Out-of-Scope) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While initial development is code-first, the Orchestrator anticipates future integration of tools such as: + +- Static analyzers to validate resource allocation. +- Timing validation tools (end-to-end latency calculators). +- Visualization tools mapping Program execution onto system resources and cores. + +System Observability +-------------------- + +Effective observability in systems requires correlation across application logic, user-space task scheduling, and kernel-level scheduling behavior. To facilitate this, the Executor and Orchestrator frameworks expose structured tracing and metrics that enable developers and integrators to analyze, debug, and validate the system comprehensively. + +Observability Correlation +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Observability in this architecture spans three layers: + +1. **Orchestrator-level Observability**: + + - Program transitions and execution flow (entry, exit, branching decisions). + - Timing monitor status, including deadline tracking and violations. + - Event timing and synchronization points. + +2. **Executor-level Observability**: + + - Task lifecycle events: creation, scheduling, yielding, completion, or rejection. + - Executor queue metrics, including load and scheduling delays. + - Mapping and correlation of user-space tasks to OS-level threads. + +3. **OS Scheduler Correlation**: + + - Visibility into OS thread scheduling decisions (context switches, core affinity adherence). + - Identification of potential CPU starvation or blocking behaviors impacting task execution. + +To achieve comprehensive observability, the system exposes standardized trace points. + +Integration with Tracing Tools +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The trace points are designed to integrate seamlessly with established tracing frameworks, such as e.g. Perfetto and LTTng. This ensures compatibility with existing system analysis tooling and minimizes additional overhead for trace processing and visualization. The tracing framework itself, however, is considered out of scope for the orchestrator feature request (see tracing feature). + +External Supervision +-------------------- + +The Executor and Orchestrator frameworks expose observability hooks to integrate with external supervisory systems, such as systemd's watchdog or custom health monitors. These hooks provide mechanisms for external entities to verify and validate the health of Executors and Programs without requiring direct task-level instrumentation. + +The Executor and Programs are considered healthy when: + +- Either all timing constraints (execution monitors) within Programs are consistently satisfied, or the defined error-handling logic within Programs executes correctly and completely in response to any timing violations or other faults. +- And critical tasks are executed reliably, with no instances of starvation, deadlocks, or indefinite blocking observed within Executors. + +The design ensures tasks themselves do not require explicit interfacing with external monitoring mechanisms. Instead, Executor and Program frameworks transparently integrate health checkpoints internally. The external health monitor is considered out of scope for the orchestrator feature request (see lifecycle and health feature). + + + +.. Backwards Compatibility +.. ======================= + + +Security Impact +=============== + +.. note:: + + This section does not replace a formal security impact analysis. This only guides the design thoughts behind security related topics and is to be understood as a starting point for later workflows. + +The design of this orchestration feature is based on the assumption that all code executing within a process is trusted. Consequently, the attack surface within a single process is inherently minimized, as the task isolation provided by threads is secure due to the fact that threads cannot be accessed from outside the process. + +A potential attack surface arises from the synchronization between tasks or threads that belong to different processes. To mitigate this risk, the feature request mandates the exclusive use of the :ref:`communication_ipc` for any inter-process synchronization. This communication feature has been previously evaluated with regard to its security impact on synchronization primitives and is considered secure. No alternative forms of exchange or synchronization between processes are permitted for this feature. + + +Safety Impact +============= + +.. note:: + + This section does not replace a formal safety impact analysis. This only guides the design thoughts behind safety related topics and is to be understood as a starting point for later workflows. + +The orchestration feature is designed under the assumption that all tasks within a single process share the same ASIL level. As a result, the internal task management must not mix different safety levels. In the specification section, the capability to define robust error handling mechanisms is described. These mechanisms are intended to serve as integral safety elements within an application's safety concept. Consequently, the feature must ensure that if error handling mechanisms are present, they are isolated from the effects of misbehaving tasks (for example, in the worst-case scenario where all threads in the pool become occupied by tasks in an infinite loop). This functionality shall be implemented in a configurable manner, recognizing that not all applications require safety mechanisms to be defined through the orchestration feature, and that ensuring guaranteed reactivity typically incurs a cost. + +In addition, the orchestration feature must expose hooks for external supervision of its safety mechanisms. These hooks enable integration with an external watchdog, while the feature itself will not directly connect to a watchdog, thereby preserving platform maintainability. + +Finally, for mixed-criticality deployments the feature shall enforce that all tasks within a thread pool (or process) have the same criticality level. Lower-criticality tasks must not influence the timing behavior of higher-criticality tasks. This is achieved by leveraging the OS's preemptive scheduling between thread pools, and by managing inter-process synchronization exclusively via the :ref:`communication_ipc`, which is already validated for this purpose. + + +.. License Impact +.. ============== + + +How to Teach This +================== +A good first read is The Rust Async Book [#s1]_. It helps to get a better understanding of how user-level context switching and cooperative multi-tasking works in theory. Additionally, the referenced material in the :ref:`footnotes` can be used to get more familiar with the problem statements and proposed solution of the feature request. + +.. Rejected Ideas +.. ============== + +.. Open Issues +.. =========== + +Glossary +======== + +.. glossary:: + + task + A lightweight, independently schedulable unit of execution managed in user space. Typically represents a future, coroutine, or async function. + + thread + The smallest sequence of programmed instructions that can be managed independently by an operating system. Threads share a process's resources, such as memory, and are scheduled by the operating system or by user-level schedulers. + + concurrent + The ability of a system to manage multiple tasks over overlapping time periods. Concurrency does not necessarily mean that tasks are executed simultaneously, but rather that progress can be made on more than one task during the same time interval. + + parallel + The simultaneous execution of multiple tasks on different processing units, such as CPU cores. Parallelism is a subset of concurrency and is used to speed up processing by dividing tasks among available hardware resources. + + cooperative + A scheduling model in which tasks voluntarily yield control to enable other tasks to execute. In cooperative multitasking, task switching occurs at well-defined points, reducing the overhead of context switching and simplifying the management of shared resources. + + preemptive + A scheduling model where task execution can be interrupted externally. + + fairness-based scheduling + A scheduling strategy that aims to ensure all ready tasks or threads are given equitable opportunities to progress over time. In cooperative scheduling (e.g., async executors), this involves polling tasks in a way that prevents any single task from monopolizing the scheduler, assuming tasks yield control appropriately. In preemptive systems, it ensures that no runnable thread is starved of CPU time. Fairness may be implemented via round-robin, aging, or probabilistic approaches, but it does not guarantee strict time-sharing. + + program + A static, declarative graph that defines the control flow and timing semantics of an application's task logic. + + application + The smallest individually updateable software unit from a deployment or system architecture point of view. An application may contain one or more programs, which are the unit of execution logic. + + +.. _footnotes: + +Footnotes +========= + +.. [#s1] "Asynchronous Programming in Rust", https://rust-lang.github.io/async-book/ diff --git a/docs/features/orchestration/requirements.rst b/docs/features/orchestration/requirements.rst new file mode 100644 index 0000000000..bbb4b40238 --- /dev/null +++ b/docs/features/orchestration/requirements.rst @@ -0,0 +1,383 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +Requirements +############# + +.. evaluate following sth requirements: +.. com driven: +.. stkh_req__app_architectures__support_time +.. stkh_req__app_architectures__support_data +.. stkh_req__app_architectures__support_request +.. stkh_req__communication__service_quality + +.. compute driven: +.. stkh_req__execution_model__processes +.. stkh_req__dev_experience__tracing_of_exec + +.. safety: +.. stkh_req__dependability__automotive_safety +.. stkh_req__functional_req__safe_comput + +.. security: +.. stkh_req__dependability__security_features + +.. accelerators: +.. stkh_req__functional_req__hardware_comput +.. stkh_req__functional_req__comp_subsystem + + + +Executor +======== + +Task Management +--------------- + + +.. TODO: set invalid requirements to valid once bug regarding tracing ASIL and QM sth req is solved + +.. feat_req:: Async Cooperative Task Runtime + :id: feat_req__orchestration__exec_async_rt + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + The executor shall provide a cooperative task runtime for async programming based on the definition of Rust's async model (see `Asynchronous Programming in Rust <https://rust-lang.github.io/async-book>`). + +.. feat_req:: Yielding Guidelines for Long Operations + :id: feat_req__orchestration__exec_yielding + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + The executor shall provide guidelines for dividing long-running operations into smaller, cooperatively yielding segments. + +.. feat_req:: Dedicated Threads for Blocking Operations + :id: feat_req__orchestration__exec_block_threads + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + The system shall support execution of tasks containing blocking calls on dedicated OS threads isolated from cooperative scheduling. + +Special Tasks and Preemption +---------------------------- + +.. feat_req:: Preemptive Scheduling for Safety Tasks + :id: feat_req__orchestration__exec_preempt_safety + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__execution_model__processes, stkh_req__dependability__automotive_safety + :status: invalid + + The Executor shall support preemptive scheduling of special safety-critical tasks, guaranteeing their execution. + +.. feat_req:: Separate Priority for Safety Tasks + :id: feat_req__orchestration__exec_safe_task_prio + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__execution_model__processes, stkh_req__dependability__automotive_safety + :status: invalid + + Safety-critical tasks shall be prioritized separately from standard cooperative tasks. + +Thread Pool Configuration +-------------------------- + +.. feat_req:: Fixed-Size Thread Pool + :id: feat_req__orchestration__exec_fixed_pool + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Executor instances shall run tasks on a statically configured thread pool with a fixed thread count. + +.. feat_req:: Uniform OS Priority for Non-Safety Threads + :id: feat_req__orchestration__exec_os_prio + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Threads within an Executor not involved in safety-critical tasks shall share identical OS-level priority. + +.. feat_req:: Configurable Thread Affinity + :id: feat_req__orchestration__exec_thread_aff + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Thread affinity to CPU cores shall be configurable per Executor instance. + +.. feat_req:: Isolated Thread Pools + :id: feat_req__orchestration__exec_pool_isolation + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Executor instances shall isolate their thread pools from each other. + +Task Scheduling +--------------- + +.. feat_req:: No Internal Priorities for Cooperative Tasks + :id: feat_req__orchestration__exec_no_int_prios + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Cooperative tasks within an Executor shall execute without internal priority distinctions. + +.. feat_req:: FIFO or Fairness Scheduling + :id: feat_req__orchestration__exec_fifo_fair_sched + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + The Executor shall support FIFO or fairness-based scheduling among cooperative tasks. + +.. feat_req:: Scale via Additional Executors + :id: feat_req__orchestration__exec_scale_instances + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Scaling of Executor resources shall be achieved through additional Executor instances rather than dynamic thread scaling. + +Orchestrator Requirements +========================= + +Program Definition +------------------ + +.. feat_req:: Static Program Execution Graphs + :id: feat_req__orchestration__orch_static_graphs + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + The Orchestrator shall provide a runtime-static Program abstraction representing computation logic as execution graphs. + +.. feat_req:: Explicit Control Flows and Timing + :id: feat_req__orchestration__orch_ctrl_flows + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Programs shall explicitly define sequential, parallel, conditional execution flows, loops, and timing contracts. + +.. feat_req:: Event-Based Synchronization + :id: feat_req__orchestration__orch_event_sync + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Programs shall support explicit event-based synchronization and trigger conditions. + +.. feat_req:: Fault-Handling and Monitors + :id: feat_req__orchestration__orch_fault_mon + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Programs shall contain integrated fault-handling logic and execution monitors to enforce timing constraints. + +API Design +---------- + +.. feat_req:: Code-First Integration API + :id: feat_req__orchestration__orch_code_api + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + The Orchestrator shall offer a code-first API to integrate directly with application logic without external DSL/IDL. + +Execution Model +--------------- + +.. feat_req:: Single-Executor Deployment + :id: feat_req__orchestration__orch_single_deploy + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Each Program shall be deployed exclusively on a single Executor instance. + +.. feat_req:: Multi-Program Support per Executor + :id: feat_req__orchestration__orch_multi_prog + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Executors may host multiple Programs to support resource sharing. + +.. feat_req:: Event-Only Communication + :id: feat_req__orchestration__orch_event_comm + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time + :status: valid + + Programs shall communicate exclusively through explicitly defined events. + +Special Safety Task Integration +------------------------------- + +.. feat_req:: Safety Tasks in Programs + :id: feat_req__orchestration__orch_safety_tasks + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__execution_model__processes, stkh_req__dependability__automotive_safety + :status: invalid + + Critical timing or safety paths within Programs shall be executed via preemptive special tasks provided by the Executor. + +Observability Requirements +========================== + +.. feat_req:: Trace Correlation Points + :id: feat_req__orchestration__obsv_trace_corr + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__dev_experience__tracing_of_exec + :status: valid + + The Executor and Orchestrator shall expose structured tracing points correlating user-space task scheduling with OS-level scheduling. + +.. feat_req:: Task Lifecycle and Queue Metrics + :id: feat_req__orchestration__obsv_lifecycle_qm + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__dev_experience__tracing_of_exec + :status: valid + + Observability shall capture task lifecycle events, Executor queue metrics, and mapping of user-space tasks to OS threads. + +.. feat_req:: Program Flow and Timing Visibility + :id: feat_req__orchestration__obsv_flow_vis + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__dev_experience__tracing_of_exec + :status: valid + + Observability shall provide visibility into Program execution flow, event synchronization points, and timing violations. + +.. feat_req:: Integration with Tracing Frameworks + :id: feat_req__orchestration__obsv_fw_integ + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes, stkh_req__dev_experience__tracing_of_exec + :status: valid + + Tracing points shall integrate seamlessly with established tracing frameworks like Perfetto and LTTng. + +External Supervision Requirements +================================= + +.. feat_req:: Health Indicators Export + :id: feat_req__orchestration__ext_health_inds + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Executor and Orchestrator frameworks shall expose health indicators for integration with external supervisory systems. + +.. feat_req:: Internal Task Health Verification + :id: feat_req__orchestration__ext_task_health + :reqtype: Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + Frameworks shall internally verify task-level health status based on timing constraints and fault-handling execution. + +General Constraints +=================== + +.. feat_req:: Determinism and Scalability + :id: feat_req__orchestration__gen_det_scale + :reqtype: Non-Functional + :security: NO + :safety: QM + :satisfies: stkh_req__execution_model__processes + :status: valid + + The Executor and Orchestrator shall maintain determinism and scalability suitable for mixed-criticality environments. + +.. feat_req:: Explicit Preemption Activation + :id: feat_req__orchestration__gen_preempt_act + :reqtype: Functional + :security: NO + :safety: ASIL_B + :satisfies: stkh_req__execution_model__processes, stkh_req__dependability__automotive_safety + :status: invalid + + Preemptive scheduling shall only be activated explicitly for tasks with safety or critical timing constraints. + +.. feat_req:: Exclusive Use of IPC Feature for Inter Process Synchronization + :id: feat_req__orchestration__gen_excl_ipc + :reqtype: Non-Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__execution_model__processes, stkh_req__dependability__automotive_safety, stkh_req__dependability__security_features, stkh_req__communication__inter_process + :status: invalid + + The system shall use the approved IPC feature exclusively for all inter-process synchronization. From e668c99e58fefccb84cc1a9fa638cac8b7af788d Mon Sep 17 00:00:00 2001 From: aschemmel-tech <aschemmel_job@arcor.de> Date: Tue, 22 Jul 2025 16:24:59 +0200 Subject: [PATCH 089/102] Module release guide align with PMP (#1486) Ref: Resolves #1480 --- docs/contribute/general/release_guide.rst | 47 ++++++++++--------- .../release_management.rst | 11 ++++- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/docs/contribute/general/release_guide.rst b/docs/contribute/general/release_guide.rst index 2fc1560057..e291f1dd7a 100644 --- a/docs/contribute/general/release_guide.rst +++ b/docs/contribute/general/release_guide.rst @@ -12,17 +12,17 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _module_release_guide: +.. _module_release_manual: -Module Release Guide -==================== +Module Release Manual +===================== Overview -------- -In order to use different Modules via the Bazel ecosystem, the Modules have to be released and registered in the S-CORE Bazel Registry. -This short guide will show you the steps necessary to create a release and make it available for other Bazel Modules. +In order to use different Modules via the Bazel ecosystem, the Modules have to be released and registered in the S-CORE Bazel Registry. +This short manual will show you the steps necessary to create a release and make it available for other Bazel Modules. Prerequisites ------------- @@ -34,7 +34,7 @@ Before starting the release process, ensure you have: - All necessary changes merged into the main branch - Understanding of semantic versioning principles -For further and more detailed information take a look at the `Release Management Process <https://eclipse-score.github.io/score/pr-1445/platform_management_plan/release_management.html>`_ +For further and more detailed information take a look at the :need:`doc__platform_release_management_plan`. Module Release Process ---------------------- @@ -58,7 +58,7 @@ Ensure that the ``MODULE.bazel`` version matches the version you are about to re compatibility_level = 0, ) -.. important:: +.. important:: *If the version in the MODULE.bazel is different from the one you want to release, you need to update them to match* Follow semantic versioning (SemVer) principles: @@ -69,14 +69,14 @@ Follow semantic versioning (SemVer) principles: * **PATCH**: Incremented for backward-compatible bug fixes. -For a more detailed description of when to update which version look at the process `here <https://eclipse-score.github.io/score/pr-1445/platform_management_plan/release_management.html#identification>`_ +For a more detailed description of when to update which version look at the "Identification" section of :need:`doc__platform_release_management_plan` -If you have a major version change that **breaks** backwards compatibility, then make sure to also increase the -compatibility level inside the MODULE.bazel file. +If you have a major version change that **breaks** backwards compatibility, then make sure to also increase the +compatibility level inside the MODULE.bazel file. The compatibility level should be the lowest supported major version that this new version is still compatible with. -3. Create GitHub Release +1. Create GitHub Release ~~~~~~~~~~~~~~~~~~~~~~~~ Create a new release: @@ -93,7 +93,7 @@ b. On the right-hand side, click 'Create a new release' .. image:: _assets/Releases_other_way.png :width: 800 - :alt: Github Release Alternate Look + :alt: Github Release Alternate Look **If this is the case, you then can create a new release via this button on the following screen.** @@ -126,7 +126,7 @@ Create a new tag following the format ``vx.y.z`` (e.g., ``v1.2.3``): 5. Write Release Notes ~~~~~~~~~~~~~~~~~~~~~~ -Add meaningful release notes that document the changes you made since your last release. +Add meaningful release notes that document the changes you made since your last release. You can use the generate release notes button to get a good starting point. @@ -142,6 +142,9 @@ This then will give you something similar to this: :width: 400 :alt: Generated Release Notes +For an official release (note) you need to consider the :need:`doc__platform_release_management_plan` +and follow the process as in :need:`PROCESS_gd_guidl__rel_management`. + 6. Set Pre-release Status (if applicable) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -167,10 +170,10 @@ Copy the ``MODULE.bazel`` file from your released version to the registry struct # Navigate to your local copy of the Bazel Central Registry cd bazel-central-registry - + # Create the module directory structure if it doesn't exist mkdir -p modules/your_module_name/x.y.z - + # Copy the MODULE.bazel file cp /path/to/your/project/MODULE.bazel modules/your_module_name/x.y.z/ @@ -182,8 +185,8 @@ Calculate the SHA256 hash of the release archive via the following command: .. code-block:: bash curl -Ls "https://github.com/your_org/your_repo/archive/refs/tags/vx.y.z.tar.gz" | sha256sum | awk '{ print $1 }' | xxd -r -p | base64 | sed 's/^/sha256-/' - - # output will look something like this: + + # output will look something like this: # sha256-s48hf6x3E7XvwgnrDMnKI/97PZju4haQnF0AnPXK9VE= @@ -230,8 +233,8 @@ Here is an example file .. code-block:: json :caption: Example metadata.json file - - { + + { "homepage": "<the homepage of your repository / documentation>", "maintainers": [ { @@ -247,7 +250,7 @@ Here is an example file "versions": [ "0.0.7", "0.0.8", - "0.1.0" + "0.1.0" ], "yanked_versions": {} } @@ -286,7 +289,5 @@ Users can now add your Module to their ``MODULE.bazel`` file: bazel_dep(name = "your_module_name", version = "x.y.z") - # example + # example # bazel_dep(name = "score_process", version = "1.0.4") - - diff --git a/docs/platform_management_plan/release_management.rst b/docs/platform_management_plan/release_management.rst index 0d4f456097..1d2cd2290b 100644 --- a/docs/platform_management_plan/release_management.rst +++ b/docs/platform_management_plan/release_management.rst @@ -58,8 +58,13 @@ Release types are strongly associated with the release version numbering, which "Identification" section below. S-CORE has two major kinds of releases: experimental and official. These correspond with the "feature flags" -defined in :need:`doc__project_mgt_plan`. Experimental means that the development artefacts needed for -the safety package work products may be incomplete and will be identified as "Pre-Release" versions. +defined in :need:`doc__project_mgt_plan`. + +* **Experimental** means that the development artefacts needed for the safety package work products may be incomplete. + These releases are done during development phase to be able to sync between the module repositories. +* **Official** means that the processes are fully executed to produce all work products and are documented + with a releae note as in :need:`PROCESS_gd_temp__rel__plat_rel_note` or :need:`PROCESS_gd_temp__rel__mod_rel_note`. + For an official release also consider `Eclipse Project Handbook - Releases <https://www.eclipse.org/projects/handbook/#release-releases>`_. Release Planning and Execution @@ -80,6 +85,8 @@ As defined in the process, the releases on module and platform level need to be Major version updates denote API incompatibility, so the modules in a platform release are expected to have the same major version. +For the release execution follow the steps described in :ref:`module_release_manual`. + Identification ^^^^^^^^^^^^^^ From bed608fdee0a1f1539f0952fef7c44a52dae65d8 Mon Sep 17 00:00:00 2001 From: Armin Bartsch <armin.bartsch@accenture.com> Date: Mon, 2 Jun 2025 11:55:49 +0200 Subject: [PATCH 090/102] FEO feat. request and requirements: Add error handling according to #944 closes: #944 Change-Id: I0c8ef7ba216f378d1c0f1ce318e9773d70657573 --- docs/features/frameworks/feo/index.rst | 37 +++++++++ .../frameworks/feo/requirements/index.rst | 80 +++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/docs/features/frameworks/feo/index.rst b/docs/features/frameworks/feo/index.rst index e8fc8d66d9..b203dfe2b3 100644 --- a/docs/features/frameworks/feo/index.rst +++ b/docs/features/frameworks/feo/index.rst @@ -436,3 +436,40 @@ w.r.t impact of computation load and latency. .. |example_task_chain_3_threads_optimized| image:: _assets/example_task_chain_3_threads_optimized.png .. |example_task_chain_3_threads_dynamic| image:: _assets/example_task_chain_3_threads_dynamic.png + + +Error Handling +============== + +Possible error cases during the different FEO life cycle states shall be handled as follows. + +* Independent of state + - If the primary process dies, the external lifecycle management shall kill all dependent processes. + - If a secondary process dies, the lifecycle management shall send a termination signal to the primary process. + The primary process shall call the shutdown function of all remaining activities in arbitrary sequence and + terminate itself. + +* State: Lifecycle Manger creates all processes (primary & secondaries) + - If one or more processes cannot be created, the problem will be handled directly by the Lifecycle Manager + (e.g. system restart / retry) + - If not all secondaries connect to the primary in time, the primary shall report an error to the + lifecycle/health management. The startup functions shall not be triggered. + +* State: Lifecycle Manager has created all processes (primary & secondaries), all secondaries have connected to the primary + - If an error occurs during the execution of a startup function, the primary process shall abort calling + startup functions, report the issue to health management and terminate itself. For all of the activities + whose startup functions have already been called successfully, the corresponding shutdown functions shall be + executed in arbitrary sequence. + - If a timeout occurs during startup, stepping or shutdown of an activity, the issue shall be reported to + health-management. The primary process shall shutdown all successfully started activities in arbitrary sequence + and terminate itself. + +* State: Lifecycle Manager has created all processes (primary & secondaries), all secondaries have connected to the primary, all activities have been started up successfully + - If an activity fails in the step function, a logical waypoint error shall be reported to health management. + The primary process shall call shutdown for all activities in arbitrary sequence and terminate itself. + - If activities do not meet their intermediate (time/memory/cpu-) budgets the issue shall be detected and handled + outside of FEO. (Resource supervision and quotas will be defined in a separate feature request, if needed.) + +* State: Shutdown of activities + - If an activity fails in the shutdown function, a logical waypoint error shall be reported to health management. + The primary process shall shutdown all remaining activities and terminate itself. diff --git a/docs/features/frameworks/feo/requirements/index.rst b/docs/features/frameworks/feo/requirements/index.rst index 98d8e4ebcc..6ecaf45b2c 100644 --- a/docs/features/frameworks/feo/requirements/index.rst +++ b/docs/features/frameworks/feo/requirements/index.rst @@ -211,3 +211,83 @@ Supervision This can be done e.g. via evaluation of floating point exceptions, checking of hardware registers or status information of the software platform. + + +Error Handling +============== + +.. feat_req:: Response to termination request + :id: feat_req__feo__response_term_request + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If the primary process receives a termination signal from the Lifecycle Manager, it shall call the shutdown + function of all remaining activities in arbitrary sequence and terminate itself. + + If a secondary process receives a termination signal from the Lifecycle Manager, it shall terminate itself. + + +.. feat_req:: Secondary connection timeout + :id: feat_req__feo__secondary_conn_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If not all secondary processes connect to the primary in time, the primary shall report an error to the + lifecycle/health management. The startup functions shall not be triggered. + + +.. feat_req:: Activity startup error + :id: feat_req__feo__act_startup_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If an error occurs during the execution of a startup function, the primary process shall abort calling + startup functions, report the issue to health management and terminate itself. For all of the activities + whose startup functions have already been called successfully, the corresponding shutdown functions shall be + executed in arbitrary sequence. + + +.. feat_req:: Activity timeout + :id: feat_req__feo__act_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If a timeout occurs during startup, stepping or shutdown of an activity, the issue shall be reported to + health-management. The primary process shall shutdown all successfully started activities in arbitrary sequence + and terminate itself. + + +.. feat_req:: Activity stepping error + :id: feat_req__feo__act_stepping_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If an activity fails in the step function, a logical waypoint error shall be reported to health management. + The primary process shall call shutdown for all activities in arbitrary sequence and terminate itself. + + +.. feat_req:: Activity shutdown error + :id: feat_req__feo__act_shutdown_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If an activity fails in the shutdown function, a logical waypoint error shall be reported to health management. + The primary process shall shutdown all remaining activities and terminate itself. From a3e1c9b8e38ef1b1ed4d7a85b7f1e1dbfb7c4696 Mon Sep 17 00:00:00 2001 From: "armin.bartsch" <armin.bartsch@accenture.com> Date: Fri, 27 Jun 2025 15:56:40 +0200 Subject: [PATCH 091/102] Update feature request and requirements after review. ref: none Change-Id: Id8d39315c2ea5cd875db3d9f9e16db29fa2aac0d --- docs/features/frameworks/feo/index.rst | 7 +++- .../frameworks/feo/requirements/index.rst | 35 ++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/features/frameworks/feo/index.rst b/docs/features/frameworks/feo/index.rst index b203dfe2b3..6e84c61251 100644 --- a/docs/features/frameworks/feo/index.rst +++ b/docs/features/frameworks/feo/index.rst @@ -449,7 +449,7 @@ Possible error cases during the different FEO life cycle states shall be handled The primary process shall call the shutdown function of all remaining activities in arbitrary sequence and terminate itself. -* State: Lifecycle Manger creates all processes (primary & secondaries) +* State: Lifecycle Manager creates all processes (primary & secondaries) - If one or more processes cannot be created, the problem will be handled directly by the Lifecycle Manager (e.g. system restart / retry) - If not all secondaries connect to the primary in time, the primary shall report an error to the @@ -460,9 +460,14 @@ Possible error cases during the different FEO life cycle states shall be handled startup functions, report the issue to health management and terminate itself. For all of the activities whose startup functions have already been called successfully, the corresponding shutdown functions shall be executed in arbitrary sequence. + - During initialization (i.e. in the startup function of an activity), activities shall check for resource allocation + and report an error to the executor in case of failure. - If a timeout occurs during startup, stepping or shutdown of an activity, the issue shall be reported to health-management. The primary process shall shutdown all successfully started activities in arbitrary sequence and terminate itself. + - If not all activities reach their initialized state within a certain period of time (startup timeout), + the issue shall be reported to health-management. The primary process shall shutdown all successfully + started activities in arbitrary sequence and terminate itself. * State: Lifecycle Manager has created all processes (primary & secondaries), all secondaries have connected to the primary, all activities have been started up successfully - If an activity fails in the step function, a logical waypoint error shall be reported to health management. diff --git a/docs/features/frameworks/feo/requirements/index.rst b/docs/features/frameworks/feo/requirements/index.rst index 6ecaf45b2c..163b2f3d7d 100644 --- a/docs/features/frameworks/feo/requirements/index.rst +++ b/docs/features/frameworks/feo/requirements/index.rst @@ -58,7 +58,7 @@ Definitions :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data + :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data, stkh_req__execution_model__processes :status: valid All activities within an application are arranged within a `Task Chain`. @@ -113,7 +113,7 @@ Dynamic Architecture :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data + :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data, stkh_req__execution_model__processes :status: valid The Application Lifecycle consists of 3 phases: Init, Run and Shutdown. @@ -123,7 +123,7 @@ Dynamic Architecture :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data + :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data, stkh_req__execution_model__processes :status: valid Initialization of activities is done during application initialization. @@ -138,7 +138,7 @@ Dynamic Architecture :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data + :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data, stkh_req__execution_model__processes :status: valid Each activity is stepped once within each execution of the task chain they belong to. @@ -150,7 +150,7 @@ Dynamic Architecture :reqtype: Functional :security: NO :safety: ASIL_B - :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data + :satisfies: stkh_req__app_architectures__support_time, stkh_req__app_architectures__support_data, stkh_req__execution_model__processes :status: valid Shutdown of activities is done during application shutdown. @@ -256,6 +256,18 @@ Error Handling executed in arbitrary sequence. +.. feat_req:: Activity resource allocation error + :id: feat_req__feo__act_alloc_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + During initialization (i.e. in the startup function of an activity), activities shall check for resource allocation + and report an error to the executor in case of failure. + + .. feat_req:: Activity timeout :id: feat_req__feo__act_timeout :reqtype: Functional @@ -269,6 +281,19 @@ Error Handling and terminate itself. +.. feat_req:: Startup timeout + :id: feat_req__feo__startup_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes + :status: valid + + If not all activities reach their initialized state within a certain period of time (startup timeout), + the issue shall be reported to health-management. The primary process shall shutdown all successfully + started activities in arbitrary sequence and terminate itself. + + .. feat_req:: Activity stepping error :id: feat_req__feo__act_stepping_error :reqtype: Functional From f2ae9a56aeb96f71231cc2a49f294594565e4768 Mon Sep 17 00:00:00 2001 From: "armin.bartsch" <armin.bartsch@accenture.com> Date: Mon, 21 Jul 2025 12:50:16 +0200 Subject: [PATCH 092/102] FEO error handling spec. limited to V0.5, comp. requ. adapted ref: none Change-Id: I1b487bd87b3d7ab8e1feb2cac0fd228f552c73c8 --- docs/features/frameworks/feo/index.rst | 47 ++++---- .../requirements/component_requirements.rst | 102 ++++++++++++++++++ .../frameworks/feo/requirements/index.rst | 30 +++--- 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/docs/features/frameworks/feo/index.rst b/docs/features/frameworks/feo/index.rst index 6e84c61251..4e04e3d2b6 100644 --- a/docs/features/frameworks/feo/index.rst +++ b/docs/features/frameworks/feo/index.rst @@ -438,10 +438,12 @@ w.r.t impact of computation load and latency. .. |example_task_chain_3_threads_dynamic| image:: _assets/example_task_chain_3_threads_dynamic.png -Error Handling -============== +Error Handling for S-CORE v0.5 +============================== -Possible error cases during the different FEO life cycle states shall be handled as follows. +Possible error cases during the different FEO life cycle states shall be handled as follows. For now, the +descriptions are focussed on the intended implementation for S-CORE v0.5. Potential adaptations for +S-CORE v1.0 have been noted down, but shall be considered as drafts only. * Independent of state - If the primary process dies, the external lifecycle management shall kill all dependent processes. @@ -450,31 +452,36 @@ Possible error cases during the different FEO life cycle states shall be handled terminate itself. * State: Lifecycle Manager creates all processes (primary & secondaries) - - If one or more processes cannot be created, the problem will be handled directly by the Lifecycle Manager - (e.g. system restart / retry) - - If not all secondaries connect to the primary in time, the primary shall report an error to the - lifecycle/health management. The startup functions shall not be triggered. + - If not all secondaries connect to the primary in time, + - S-CORE v0.5: the primary will terminate itself. The startup functions shall not be triggered. + - S-CORE v1.0: the primary will not terminate, but report an error to the lifecycle/health management. + The startup functions shall not be triggered. * State: Lifecycle Manager has created all processes (primary & secondaries), all secondaries have connected to the primary - - If an error occurs during the execution of a startup function, the primary process shall abort calling - startup functions, report the issue to health management and terminate itself. For all of the activities - whose startup functions have already been called successfully, the corresponding shutdown functions shall be - executed in arbitrary sequence. + - If an error occurs during the execution of a startup function, + - S-CORE v0.5: the primary process shall abort calling startup functions + and terminate itself. For all of the activities whose startup functions have already been called successfully, + the corresponding shutdown functions shall be executed in arbitrary sequence. + - S-CORE v1.0: in addition, the primary process shall report the issue to health management. - During initialization (i.e. in the startup function of an activity), activities shall check for resource allocation and report an error to the executor in case of failure. - - If a timeout occurs during startup, stepping or shutdown of an activity, the issue shall be reported to - health-management. The primary process shall shutdown all successfully started activities in arbitrary sequence - and terminate itself. + - If a timeout occurs during startup, stepping or shutdown of an activity, + - S-CORE v0.5: the primary process shall shutdown all successfully started activities in arbitrary sequence + and terminate itself. + - S-CORE v1.0: In addition, the primary process shall report the issue to health management. - If not all activities reach their initialized state within a certain period of time (startup timeout), - the issue shall be reported to health-management. The primary process shall shutdown all successfully - started activities in arbitrary sequence and terminate itself. + - S-CORE v0.5: the primary process shall shutdown all successfully + started activities in arbitrary sequence and terminate itself. + - S-CORE v1.0: In addition, the primary process shall report the issue to health management. * State: Lifecycle Manager has created all processes (primary & secondaries), all secondaries have connected to the primary, all activities have been started up successfully - - If an activity fails in the step function, a logical waypoint error shall be reported to health management. - The primary process shall call shutdown for all activities in arbitrary sequence and terminate itself. + - If an activity fails in the step function, + - S-CORE v0.5: the primary process shall call shutdown for all activities in arbitrary sequence and terminate itself. + - S-CORE v1.0: In addition, a logical waypoint error shall be reported to health management. - If activities do not meet their intermediate (time/memory/cpu-) budgets the issue shall be detected and handled outside of FEO. (Resource supervision and quotas will be defined in a separate feature request, if needed.) * State: Shutdown of activities - - If an activity fails in the shutdown function, a logical waypoint error shall be reported to health management. - The primary process shall shutdown all remaining activities and terminate itself. + - If an activity fails in the shutdown function, + - S-CORE v0.5: the primary process shall shutdown all remaining activities and terminate itself. + - S-CORE v1.0: In addition, a logical waypoint error shall be reported to health management. diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst index 72e151e0fd..a44e4adc5b 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst +++ b/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst @@ -264,3 +264,105 @@ Component Requirements: feo This can be done e.g. via evaluation of floating point exceptions, checking of hardware registers or status information of the software platform. + +Error Handling for S-CORE v0.5 +============================== + +.. comp_req:: Response to termination request + :id: comp_req__feo__response_term_request + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__response_term_request + :status: valid + + If the primary process receives a termination signal, it shall call the shutdown + function of all remaining activities in arbitrary sequence and terminate itself. + + If a secondary process receives a termination signal, it shall terminate itself. + + +.. comp_req:: Secondary connection timeout + :id: comp_req__feo__secondary_conn_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__secondary_conn_timeout + :status: valid + + If not all secondary processes connect to the primary in time, the primary shall terminate itself. + The startup functions shall not be triggered. + + +.. comp_req:: Activity startup error + :id: comp_req__feo__act_startup_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__act_startup_error + :status: valid + + If an error occurs during the execution of a startup function, the primary process shall abort calling + startup functions and terminate itself. For all of the activities + whose startup functions have already been called successfully, the corresponding shutdown functions shall be + executed in arbitrary sequence. + + +.. comp_req:: Activity resource allocation error + :id: comp_req__feo__act_alloc_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__act_alloc_error + :status: valid + + During initialization (i.e. in the startup function of an activity), activities shall check for resource allocation + and report an error to the executor in case of failure. + + +.. comp_req:: Activity timeout + :id: comp_req__feo__act_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__act_timeout + :status: valid + + If a timeout occurs during startup, stepping or shutdown of an activity, the primary process shall shutdown all + successfully started activities in arbitrary sequence and terminate itself. + + +.. comp_req:: Startup timeout + :id: comp_req__feo__startup_timeout + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__startup_timeout + :status: valid + + If not all activities reach their initialized state within a certain period of time (startup timeout), + the primary process shall shutdown all successfully started activities in arbitrary sequence and terminate itself. + + +.. comp_req:: Activity stepping error + :id: comp_req__feo__act_stepping_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__act_stepping_error + :status: valid + + If an activity fails in the step function, the primary process shall call shutdown for all activities + in arbitrary sequence and terminate itself. + + +.. comp_req:: Activity shutdown error + :id: comp_req__feo__act_shutdown_error + :reqtype: Functional + :security: YES + :safety: ASIL_B + :satisfies: feat_req__feo__act_shutdown_error + :status: valid + + If an activity fails in the shutdown function, the primary process shall shutdown all remaining activities + in arbitrary sequence and terminate itself. diff --git a/docs/features/frameworks/feo/requirements/index.rst b/docs/features/frameworks/feo/requirements/index.rst index 163b2f3d7d..436d929ee5 100644 --- a/docs/features/frameworks/feo/requirements/index.rst +++ b/docs/features/frameworks/feo/requirements/index.rst @@ -213,8 +213,8 @@ Supervision software platform. -Error Handling -============== +Error Handling for S-CORE v0.5 +============================== .. feat_req:: Response to termination request :id: feat_req__feo__response_term_request @@ -224,10 +224,10 @@ Error Handling :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes :status: valid - If the primary process receives a termination signal from the Lifecycle Manager, it shall call the shutdown + If the primary process receives a termination signal, it shall call the shutdown function of all remaining activities in arbitrary sequence and terminate itself. - If a secondary process receives a termination signal from the Lifecycle Manager, it shall terminate itself. + If a secondary process receives a termination signal, it shall terminate itself. .. feat_req:: Secondary connection timeout @@ -238,8 +238,8 @@ Error Handling :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes :status: valid - If not all secondary processes connect to the primary in time, the primary shall report an error to the - lifecycle/health management. The startup functions shall not be triggered. + If not all secondary processes connect to the primary in time, the primary shall terminate itself. + The startup functions shall not be triggered. .. feat_req:: Activity startup error @@ -251,7 +251,7 @@ Error Handling :status: valid If an error occurs during the execution of a startup function, the primary process shall abort calling - startup functions, report the issue to health management and terminate itself. For all of the activities + startup functions and terminate itself. For all of the activities whose startup functions have already been called successfully, the corresponding shutdown functions shall be executed in arbitrary sequence. @@ -276,9 +276,8 @@ Error Handling :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes :status: valid - If a timeout occurs during startup, stepping or shutdown of an activity, the issue shall be reported to - health-management. The primary process shall shutdown all successfully started activities in arbitrary sequence - and terminate itself. + If a timeout occurs during startup, stepping or shutdown of an activity, the primary process shall shutdown all + successfully started activities in arbitrary sequence and terminate itself. .. feat_req:: Startup timeout @@ -290,8 +289,7 @@ Error Handling :status: valid If not all activities reach their initialized state within a certain period of time (startup timeout), - the issue shall be reported to health-management. The primary process shall shutdown all successfully - started activities in arbitrary sequence and terminate itself. + the primary process shall shutdown all successfully started activities in arbitrary sequence and terminate itself. .. feat_req:: Activity stepping error @@ -302,8 +300,8 @@ Error Handling :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes :status: valid - If an activity fails in the step function, a logical waypoint error shall be reported to health management. - The primary process shall call shutdown for all activities in arbitrary sequence and terminate itself. + If an activity fails in the step function, the primary process shall call shutdown for all activities + in arbitrary sequence and terminate itself. .. feat_req:: Activity shutdown error @@ -314,5 +312,5 @@ Error Handling :satisfies: stkh_req__dependability__safety_features, stkh_req__dependability__availability, stkh_req__execution_model__processes :status: valid - If an activity fails in the shutdown function, a logical waypoint error shall be reported to health management. - The primary process shall shutdown all remaining activities and terminate itself. + If an activity fails in the shutdown function, the primary process shall shutdown all remaining activities + in arbitrary sequence and terminate itself. From 6cfbc0b572646ebcff5719e3bd4b57382de833f5 Mon Sep 17 00:00:00 2001 From: Alexander Lanin <Alexander.Lanin@etas.com> Date: Wed, 23 Jul 2025 15:59:16 +0200 Subject: [PATCH 093/102] fix license text (#1493) --- LICENSE | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- NOTICE | 23 +++---- 2 files changed, 184 insertions(+), 23 deletions(-) diff --git a/LICENSE b/LICENSE index 5278bc9a79..f433b1a53f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,177 @@ -Copyright 2024 Contributors to the Eclipse Foundation -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - http://www.apache.org/licenses/LICENSE-2.0 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/NOTICE b/NOTICE index 9ba2a4998f..5d111d48c5 100644 --- a/NOTICE +++ b/NOTICE @@ -1,14 +1,12 @@ -# Notices for Eclipse Score +# Notices for Eclipse Safe Open Vehicle Core -This content is produced and maintained by the Eclipse Score project. +This content is produced and maintained by the Eclipse Safe Open Vehicle Core project. * Project home: https://projects.eclipse.org/projects/automotive.score ## Trademarks -Eclipse Score and Score are trademarks of the Eclipse Foundation. -Eclipse, and the Eclipse Logo are registered trademarks of -the Eclipse Foundation. +Eclipse, and the Eclipse Logo are registered trademarks of the Eclipse Foundation. ## Copyright @@ -24,12 +22,11 @@ https://www.apache.org/licenses/LICENSE-2.0. SPDX-License-Identifier: Apache-2.0 -## Source Code +## Cryptography -The project maintains the following source code repositories: - - * TBD - -## Third party Content - -TBD +Content may contain encryption software. The country in which you are currently +may have restrictions on the import, possession, and use, and/or re-export to +another country, of encryption software. BEFORE using any encryption software, +please check the country's laws, regulations and policies concerning the import, +possession, or use, and re-export of encryption software, to see if this is +permitted. From 160d47b131c93ba75abc8d940b605d2571d3a979 Mon Sep 17 00:00:00 2001 From: Arvid Sievert <arvid.sievert@etas.com> Date: Wed, 23 Jul 2025 22:05:33 +0200 Subject: [PATCH 094/102] communictaion+feo: move modules to the rigth folder (#1438) --- docs/features/communication/index.rst | 1 - docs/features/frameworks/index.rst | 1 - docs/features/orchestration/index.rst | 2 +- docs/features/orchestration/requirements.rst | 16 ++++----- .../baselibs/docs}/index.rst | 12 ++----- .../feo/docs => modules/baselibs}/index.rst | 21 +++++++----- .../json/docs/architecture/index.rst} | 2 +- .../baselibs/json/docs}/index.rst | 11 ++++--- .../docs/architecture/index.rst} | 2 +- .../baselibs/memory_shared/docs/index.rst | 23 +++++++++++++ .../docs/architecture/index.rst} | 2 +- .../baselibs/message_passing/docs/index.rst | 23 +++++++++++++ .../docs/architecture/index.rst} | 4 +-- .../configuration/docs/index.rst | 27 +++++++++++++++ .../communication/docs}/index.rst | 14 +++----- .../frontent/docs/architecture/index.rst} | 4 +-- .../communication/frontent/docs/index.rst | 27 +++++++++++++++ .../communication}/index.rst | 19 +++++++---- .../ipc_binding/docs/architecture/index.rst} | 4 +-- .../communication/ipc_binding/docs/index.rst | 27 +++++++++++++++ .../mock_binding/docs/architecture/index.rst} | 4 +-- .../communication/mock_binding/docs/index.rst | 27 +++++++++++++++ docs/modules/feo/docs/index.rst | 22 +++++++++++++ .../modules/feo/docs/manual/safety_manual.rst | 1 + .../docs/architecture/_assets/act_chain.puml | 0 .../docs/architecture/_assets/dyn_arch.puml | 0 .../docs/architecture/_assets/stat_arch.puml | 0 .../architecture/component_architecture.rst | 4 +-- .../feo => }/modules/feo/feo/docs/index.rst | 9 +++-- .../requirements/component_requirements.rst | 4 +-- .../modules/feo/feo_com/docs/index.rst | 11 +++++-- .../feo/feo_log}/docs/index.rst | 11 +++++-- .../modules/feo/feo_time/docs/index.rst | 11 +++++-- .../feo/feo_tracing}/docs/index.rst | 11 +++++-- docs/modules/feo/index.rst | 33 +++++++++++++++++++ docs/modules/index.rst | 12 +++++-- docs/modules/logging/docs/index.rst | 31 +++++++++++++++++ docs/modules/logging/index.rst | 32 ++++++++++++++++++ .../logging/docs/architecture}/index.rst | 15 +-------- docs/modules/logging/logging/docs/index.rst | 27 +++++++++++++++ .../modules/os => modules/os/docs}/index.rst | 11 +++---- docs/modules/os/index.rst | 32 ++++++++++++++++++ .../os/libc/docs/architecture/index.rst} | 4 +-- docs/modules/os/libc/docs/index.rst | 27 +++++++++++++++ .../docs/architecture/index.rst} | 4 +-- .../modules/os/message_passing/docs/index.rst | 27 +++++++++++++++ docs/modules/tracing/docs/index.rst | 31 +++++++++++++++++ docs/modules/tracing/index.rst | 32 ++++++++++++++++++ .../tracing/docs/architecture}/index.rst | 27 ++++++++------- docs/modules/tracing/tracing/docs/index.rst | 27 +++++++++++++++ 50 files changed, 611 insertions(+), 118 deletions(-) rename docs/{features/communication/modules/baselibs => modules/baselibs/docs}/index.rst (84%) rename docs/{features/frameworks/feo/modules/feo/docs => modules/baselibs}/index.rst (75%) rename docs/{features/communication/modules/baselibs/json_component_architecture.rst => modules/baselibs/json/docs/architecture/index.rst} (97%) rename docs/{features/communication/modules => modules/baselibs/json/docs}/index.rst (90%) rename docs/{features/communication/modules/baselibs/memory_shared_component_architecture.rst => modules/baselibs/memory_shared/docs/architecture/index.rst} (98%) create mode 100644 docs/modules/baselibs/memory_shared/docs/index.rst rename docs/{features/communication/modules/baselibs/message_passing_component_architecture.rst => modules/baselibs/message_passing/docs/architecture/index.rst} (97%) create mode 100644 docs/modules/baselibs/message_passing/docs/index.rst rename docs/{features/communication/modules/communication/configuration_component_architecture.rst => modules/communication/configuration/docs/architecture/index.rst} (92%) create mode 100644 docs/modules/communication/configuration/docs/index.rst rename docs/{features/communication/modules/communication => modules/communication/docs}/index.rst (86%) rename docs/{features/communication/modules/communication/frontent_component_architecture.rst => modules/communication/frontent/docs/architecture/index.rst} (97%) create mode 100644 docs/modules/communication/frontent/docs/index.rst rename docs/{features/frameworks/feo/modules => modules/communication}/index.rst (69%) rename docs/{features/communication/modules/communication/ipc_binding_architecture.rst => modules/communication/ipc_binding/docs/architecture/index.rst} (93%) create mode 100644 docs/modules/communication/ipc_binding/docs/index.rst rename docs/{features/communication/modules/communication/mock_binding_architecture.rst => modules/communication/mock_binding/docs/architecture/index.rst} (92%) create mode 100644 docs/modules/communication/mock_binding/docs/index.rst create mode 100644 docs/modules/feo/docs/index.rst rename docs/{features/frameworks/feo => }/modules/feo/docs/manual/safety_manual.rst (99%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/architecture/_assets/act_chain.puml (100%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml (100%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/architecture/_assets/stat_arch.puml (100%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/architecture/component_architecture.rst (98%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/index.rst (89%) rename docs/{features/frameworks/feo => }/modules/feo/feo/docs/requirements/component_requirements.rst (99%) rename docs/{features/frameworks/feo => }/modules/feo/feo_com/docs/index.rst (88%) rename docs/{features/frameworks/feo/modules/feo/feo_tracing => modules/feo/feo_log}/docs/index.rst (88%) rename docs/{features/frameworks/feo => }/modules/feo/feo_time/docs/index.rst (88%) rename docs/{features/frameworks/feo/modules/feo/feo_log => modules/feo/feo_tracing}/docs/index.rst (88%) create mode 100644 docs/modules/feo/index.rst create mode 100644 docs/modules/logging/docs/index.rst create mode 100644 docs/modules/logging/index.rst rename docs/{features/communication/modules/logging => modules/logging/logging/docs/architecture}/index.rst (83%) create mode 100644 docs/modules/logging/logging/docs/index.rst rename docs/{features/communication/modules/os => modules/os/docs}/index.rst (89%) create mode 100644 docs/modules/os/index.rst rename docs/{features/communication/modules/os/libc_component_architecture.rst => modules/os/libc/docs/architecture/index.rst} (98%) create mode 100644 docs/modules/os/libc/docs/index.rst rename docs/{features/communication/modules/os/message_passing_architecture.rst => modules/os/message_passing/docs/architecture/index.rst} (95%) create mode 100644 docs/modules/os/message_passing/docs/index.rst create mode 100644 docs/modules/tracing/docs/index.rst create mode 100644 docs/modules/tracing/index.rst rename docs/{features/communication/modules/tracing => modules/tracing/tracing/docs/architecture}/index.rst (84%) create mode 100644 docs/modules/tracing/tracing/docs/index.rst diff --git a/docs/features/communication/index.rst b/docs/features/communication/index.rst index 712437b522..f432f03ba7 100644 --- a/docs/features/communication/index.rst +++ b/docs/features/communication/index.rst @@ -30,7 +30,6 @@ Communication docs/**/index ipc/index - modules/index Feature flag ============ diff --git a/docs/features/frameworks/index.rst b/docs/features/frameworks/index.rst index 5a6c69a913..438d692d1a 100644 --- a/docs/features/frameworks/index.rst +++ b/docs/features/frameworks/index.rst @@ -19,4 +19,3 @@ Frameworks .. toctree:: feo/index.rst - feo/modules/index \ No newline at end of file diff --git a/docs/features/orchestration/index.rst b/docs/features/orchestration/index.rst index 68cee6a645..eb45568118 100644 --- a/docs/features/orchestration/index.rst +++ b/docs/features/orchestration/index.rst @@ -21,7 +21,7 @@ Orchestration :id: doc__orchestration :status: valid :safety: ASIL_B - :realizes: wp__feat_request + :realizes: :tags: feature_request, change_management, orchestration diff --git a/docs/features/orchestration/requirements.rst b/docs/features/orchestration/requirements.rst index bbb4b40238..69d6a6d4be 100644 --- a/docs/features/orchestration/requirements.rst +++ b/docs/features/orchestration/requirements.rst @@ -188,7 +188,7 @@ Program Definition :id: feat_req__orchestration__orch_static_graphs :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -198,7 +198,7 @@ Program Definition :id: feat_req__orchestration__orch_ctrl_flows :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -208,7 +208,7 @@ Program Definition :id: feat_req__orchestration__orch_event_sync :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -218,7 +218,7 @@ Program Definition :id: feat_req__orchestration__orch_fault_mon :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -231,7 +231,7 @@ API Design :id: feat_req__orchestration__orch_code_api :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -244,7 +244,7 @@ Execution Model :id: feat_req__orchestration__orch_single_deploy :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -254,7 +254,7 @@ Execution Model :id: feat_req__orchestration__orch_multi_prog :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid @@ -264,7 +264,7 @@ Execution Model :id: feat_req__orchestration__orch_event_comm :reqtype: Functional :security: NO - :safety: QM + :safety: ASIL_B :satisfies: stkh_req__execution_model__processes, stkh_req__app_architectures__support_time :status: valid diff --git a/docs/features/communication/modules/baselibs/index.rst b/docs/modules/baselibs/docs/index.rst similarity index 84% rename from docs/features/communication/modules/baselibs/index.rst rename to docs/modules/baselibs/docs/index.rst index ddd5429de3..97efbfe097 100644 --- a/docs/features/communication/modules/baselibs/index.rst +++ b/docs/modules/baselibs/docs/index.rst @@ -12,9 +12,6 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Baselibs Module -############### - .. mod_view_sta:: Baselibs :id: mod_view_sta__baselibs__baselibs :includes: comp_arc_sta__baselibs__json, comp_arc_sta__baselibs__message_passing, comp_arc_sta__baselibs__memory_shared @@ -25,12 +22,9 @@ Baselibs Module {{ draw_module(need(), needs) }} -Components -========== +Module Documents +================ .. toctree:: + :maxdepth: 2 :titlesonly: - - json_component_architecture - memory_shared_component_architecture - message_passing_component_architecture diff --git a/docs/features/frameworks/feo/modules/feo/docs/index.rst b/docs/modules/baselibs/index.rst similarity index 75% rename from docs/features/frameworks/feo/modules/feo/docs/index.rst rename to docs/modules/baselibs/index.rst index c22a91469b..61741f356a 100644 --- a/docs/features/frameworks/feo/modules/feo/docs/index.rst +++ b/docs/modules/baselibs/index.rst @@ -12,16 +12,21 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +Baselibs Module +############### -Module Documentation: feo -######################### +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index + +Components +========== .. toctree:: + :titlesonly: :maxdepth: 1 + :glob: - manual/safety_manual - ../feo/docs/index - ../feo_com/docs/index - ../feo_log/docs/index - ../feo_time/docs/index - ../feo_tracing/docs/index + ./*/docs/index diff --git a/docs/features/communication/modules/baselibs/json_component_architecture.rst b/docs/modules/baselibs/json/docs/architecture/index.rst similarity index 97% rename from docs/features/communication/modules/baselibs/json_component_architecture.rst rename to docs/modules/baselibs/json/docs/architecture/index.rst index 270bf0b0a9..329f4e7a88 100644 --- a/docs/features/communication/modules/baselibs/json_component_architecture.rst +++ b/docs/modules/baselibs/json/docs/architecture/index.rst @@ -13,7 +13,7 @@ # ******************************************************************************* JSON Component Architecture -=========================== +*************************** .. comp_arc_sta:: JSON :id: comp_arc_sta__baselibs__json diff --git a/docs/features/communication/modules/index.rst b/docs/modules/baselibs/json/docs/index.rst similarity index 90% rename from docs/features/communication/modules/index.rst rename to docs/modules/baselibs/json/docs/index.rst index 1b89a0130c..629d95a4bb 100644 --- a/docs/features/communication/modules/index.rst +++ b/docs/modules/baselibs/json/docs/index.rst @@ -12,11 +12,12 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Modules -======== +.. _comp_doc_json: + +json +#### .. toctree:: - :maxdepth: 1 - :glob: + :hidden: - */index + architecture/index diff --git a/docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst b/docs/modules/baselibs/memory_shared/docs/architecture/index.rst similarity index 98% rename from docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst rename to docs/modules/baselibs/memory_shared/docs/architecture/index.rst index 74ba799b12..19ac0bb81e 100644 --- a/docs/features/communication/modules/baselibs/memory_shared_component_architecture.rst +++ b/docs/modules/baselibs/memory_shared/docs/architecture/index.rst @@ -13,7 +13,7 @@ # ******************************************************************************* Memory Shared Component Architecture -==================================== +************************************ .. comp_arc_sta:: Memory Shared :id: comp_arc_sta__baselibs__memory_shared diff --git a/docs/modules/baselibs/memory_shared/docs/index.rst b/docs/modules/baselibs/memory_shared/docs/index.rst new file mode 100644 index 0000000000..b5b99cbc53 --- /dev/null +++ b/docs/modules/baselibs/memory_shared/docs/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_memory_shared: + +memory_shared +############# + +.. toctree:: + :hidden: + + architecture/index diff --git a/docs/features/communication/modules/baselibs/message_passing_component_architecture.rst b/docs/modules/baselibs/message_passing/docs/architecture/index.rst similarity index 97% rename from docs/features/communication/modules/baselibs/message_passing_component_architecture.rst rename to docs/modules/baselibs/message_passing/docs/architecture/index.rst index 40070ca6c1..9a5c760d7e 100644 --- a/docs/features/communication/modules/baselibs/message_passing_component_architecture.rst +++ b/docs/modules/baselibs/message_passing/docs/architecture/index.rst @@ -13,7 +13,7 @@ # ******************************************************************************* Message Passing Component Architecture -====================================== +************************************** .. comp_arc_sta:: Message Passing :id: comp_arc_sta__baselibs__message_passing diff --git a/docs/modules/baselibs/message_passing/docs/index.rst b/docs/modules/baselibs/message_passing/docs/index.rst new file mode 100644 index 0000000000..5bf5cee2fc --- /dev/null +++ b/docs/modules/baselibs/message_passing/docs/index.rst @@ -0,0 +1,23 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_baselib_message_passing: + +message_passing +############### + +.. toctree:: + :hidden: + + architecture/index diff --git a/docs/features/communication/modules/communication/configuration_component_architecture.rst b/docs/modules/communication/configuration/docs/architecture/index.rst similarity index 92% rename from docs/features/communication/modules/communication/configuration_component_architecture.rst rename to docs/modules/communication/configuration/docs/architecture/index.rst index 1820d04fdf..a16c31e423 100644 --- a/docs/features/communication/modules/communication/configuration_component_architecture.rst +++ b/docs/modules/communication/configuration/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Frontend Architecture -********************* +Configuration Component Architecture +************************************ .. comp_arc_sta:: Lola Configuration :id: comp_arc_sta__com__configuration diff --git a/docs/modules/communication/configuration/docs/index.rst b/docs/modules/communication/configuration/docs/index.rst new file mode 100644 index 0000000000..7fa4b2a8d2 --- /dev/null +++ b/docs/modules/communication/configuration/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_configuration: + +configuration +############# + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/features/communication/modules/communication/index.rst b/docs/modules/communication/docs/index.rst similarity index 86% rename from docs/features/communication/modules/communication/index.rst rename to docs/modules/communication/docs/index.rst index 370d9af53a..7796dc4527 100644 --- a/docs/features/communication/modules/communication/index.rst +++ b/docs/modules/communication/docs/index.rst @@ -12,9 +12,6 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Communication Module -#################### - .. mod_view_sta:: Communication :id: mod_view_sta__com__communication :includes: comp_arc_sta__com__configuration, comp_arc_sta__com__ipc_binding, comp_arc_sta__com__mock_binding, comp_arc_sta__com__frontend @@ -29,13 +26,10 @@ Communication Module comp_arc_sta__com__mock_binding -r[hidden]-> comp_arc_sta__com__configuration logic_arc_int__tracing__tracing -r[hidden]-> logic_arc_int__logging__logging -Components -========== + +Module Documents +================ .. toctree:: + :maxdepth: 2 :titlesonly: - - configuration_component_architecture - frontent_component_architecture - ipc_binding_architecture - mock_binding_architecture diff --git a/docs/features/communication/modules/communication/frontent_component_architecture.rst b/docs/modules/communication/frontent/docs/architecture/index.rst similarity index 97% rename from docs/features/communication/modules/communication/frontent_component_architecture.rst rename to docs/modules/communication/frontent/docs/architecture/index.rst index 23e9c3cf69..09d0222d24 100644 --- a/docs/features/communication/modules/communication/frontent_component_architecture.rst +++ b/docs/modules/communication/frontent/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Frontend Architecture -********************* +Frontend Component Architecture +******************************* .. comp_arc_sta:: mw::com Frontend :id: comp_arc_sta__com__frontend diff --git a/docs/modules/communication/frontent/docs/index.rst b/docs/modules/communication/frontent/docs/index.rst new file mode 100644 index 0000000000..28bf90630b --- /dev/null +++ b/docs/modules/communication/frontent/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_frontent: + +frontent +######## + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/features/frameworks/feo/modules/index.rst b/docs/modules/communication/index.rst similarity index 69% rename from docs/features/frameworks/feo/modules/index.rst rename to docs/modules/communication/index.rst index b62b90558a..781c9369da 100644 --- a/docs/features/frameworks/feo/modules/index.rst +++ b/docs/modules/communication/index.rst @@ -12,16 +12,21 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _modules: +Communication Module +#################### -Modules Documentation -##################### +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index -.. note:: - For now, we store the modules documentation in the feature tree, because multi-repo docs are not yet supported. - Once this support becomes available it will be moved to the modules tree. +Components +========== .. toctree:: + :titlesonly: :maxdepth: 1 + :glob: - feo/docs/index + ./*/docs/index diff --git a/docs/features/communication/modules/communication/ipc_binding_architecture.rst b/docs/modules/communication/ipc_binding/docs/architecture/index.rst similarity index 93% rename from docs/features/communication/modules/communication/ipc_binding_architecture.rst rename to docs/modules/communication/ipc_binding/docs/architecture/index.rst index 5453f1083c..0bbc7a6f8b 100644 --- a/docs/features/communication/modules/communication/ipc_binding_architecture.rst +++ b/docs/modules/communication/ipc_binding/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -IPC Binding Architecture -************************ +IPC Binding Component Architecture +********************************** .. comp_arc_sta:: IPC Binding :id: comp_arc_sta__com__ipc_binding diff --git a/docs/modules/communication/ipc_binding/docs/index.rst b/docs/modules/communication/ipc_binding/docs/index.rst new file mode 100644 index 0000000000..ae3fa379a0 --- /dev/null +++ b/docs/modules/communication/ipc_binding/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_ipc_binding: + +ipc_binding +########### + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/features/communication/modules/communication/mock_binding_architecture.rst b/docs/modules/communication/mock_binding/docs/architecture/index.rst similarity index 92% rename from docs/features/communication/modules/communication/mock_binding_architecture.rst rename to docs/modules/communication/mock_binding/docs/architecture/index.rst index 18d736175f..5fa3ccc783 100644 --- a/docs/features/communication/modules/communication/mock_binding_architecture.rst +++ b/docs/modules/communication/mock_binding/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Mock Binding Architecture -************************* +Mock Binding Component Architecture +*********************************** .. comp_arc_sta:: Mock binding :id: comp_arc_sta__com__mock_binding diff --git a/docs/modules/communication/mock_binding/docs/index.rst b/docs/modules/communication/mock_binding/docs/index.rst new file mode 100644 index 0000000000..4bc8c78d78 --- /dev/null +++ b/docs/modules/communication/mock_binding/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_mock_binding: + +mock_binding +############ + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/modules/feo/docs/index.rst b/docs/modules/feo/docs/index.rst new file mode 100644 index 0000000000..d58d0d1a05 --- /dev/null +++ b/docs/modules/feo/docs/index.rst @@ -0,0 +1,22 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Module Documents +================ + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + manual/safety_manual.rst diff --git a/docs/features/frameworks/feo/modules/feo/docs/manual/safety_manual.rst b/docs/modules/feo/docs/manual/safety_manual.rst similarity index 99% rename from docs/features/frameworks/feo/modules/feo/docs/manual/safety_manual.rst rename to docs/modules/feo/docs/manual/safety_manual.rst index c254001873..94b8fbbf1f 100644 --- a/docs/features/frameworks/feo/modules/feo/docs/manual/safety_manual.rst +++ b/docs/modules/feo/docs/manual/safety_manual.rst @@ -12,6 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* + FEO Module Safety Manual Draft ============================== diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml b/docs/modules/feo/feo/docs/architecture/_assets/act_chain.puml similarity index 100% rename from docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/act_chain.puml rename to docs/modules/feo/feo/docs/architecture/_assets/act_chain.puml diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml b/docs/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml similarity index 100% rename from docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml rename to docs/modules/feo/feo/docs/architecture/_assets/dyn_arch.puml diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml b/docs/modules/feo/feo/docs/architecture/_assets/stat_arch.puml similarity index 100% rename from docs/features/frameworks/feo/modules/feo/feo/docs/architecture/_assets/stat_arch.puml rename to docs/modules/feo/feo/docs/architecture/_assets/stat_arch.puml diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst b/docs/modules/feo/feo/docs/architecture/component_architecture.rst similarity index 98% rename from docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst rename to docs/modules/feo/feo/docs/architecture/component_architecture.rst index 3f0bc952c4..2eedd9e3fe 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/architecture/component_architecture.rst +++ b/docs/modules/feo/feo/docs/architecture/component_architecture.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Component Architecture: feo -=========================== +feo Component Architecture +************************** Overview -------- diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst b/docs/modules/feo/feo/docs/index.rst similarity index 89% rename from docs/features/frameworks/feo/modules/feo/feo/docs/index.rst rename to docs/modules/feo/feo/docs/index.rst index 408723fec9..3a9b66d9ed 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/index.rst +++ b/docs/modules/feo/feo/docs/index.rst @@ -14,12 +14,15 @@ .. _comp_doc_feo: -Component Documentation: feo -############################ +feo +### +Component Documents +=================== .. toctree:: - :maxdepth: 1 + :maxdepth: 2 + :titlesonly: architecture/component_architecture requirements/component_requirements diff --git a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst b/docs/modules/feo/feo/docs/requirements/component_requirements.rst similarity index 99% rename from docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst rename to docs/modules/feo/feo/docs/requirements/component_requirements.rst index a44e4adc5b..0a35049d13 100644 --- a/docs/features/frameworks/feo/modules/feo/feo/docs/requirements/component_requirements.rst +++ b/docs/modules/feo/feo/docs/requirements/component_requirements.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Component Requirements: feo -########################### +Requirements +############ .. comp_req:: Application Processes :id: comp_req__feo__application diff --git a/docs/features/frameworks/feo/modules/feo/feo_com/docs/index.rst b/docs/modules/feo/feo_com/docs/index.rst similarity index 88% rename from docs/features/frameworks/feo/modules/feo/feo_com/docs/index.rst rename to docs/modules/feo/feo_com/docs/index.rst index e290bbc1f8..b1f05aa5d3 100644 --- a/docs/features/frameworks/feo/modules/feo/feo_com/docs/index.rst +++ b/docs/modules/feo/feo_com/docs/index.rst @@ -13,8 +13,15 @@ # ******************************************************************************* -Component Documentation: feo_com -################################ +feo_com +####### This component will be replaced by or become a wrapper of the interface `mw::com` provided by the feature "Communication". In the latter case, it is planned to be integrated into the component feo (see :ref:`comp_doc_feo`). + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/features/frameworks/feo/modules/feo/feo_tracing/docs/index.rst b/docs/modules/feo/feo_log/docs/index.rst similarity index 88% rename from docs/features/frameworks/feo/modules/feo/feo_tracing/docs/index.rst rename to docs/modules/feo/feo_log/docs/index.rst index e00e9cd8b0..5195cf9472 100644 --- a/docs/features/frameworks/feo/modules/feo/feo_tracing/docs/index.rst +++ b/docs/modules/feo/feo_log/docs/index.rst @@ -13,8 +13,15 @@ # ******************************************************************************* -Component Documentation: feo_tracing -#################################### +feo_log +####### This component will be replaced by or become a wrapper of the interface `mw::com` provided by the feature "Logging". In the latter case, it is planned to be integrated into the component feo (see :ref:`comp_doc_feo`). + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/features/frameworks/feo/modules/feo/feo_time/docs/index.rst b/docs/modules/feo/feo_time/docs/index.rst similarity index 88% rename from docs/features/frameworks/feo/modules/feo/feo_time/docs/index.rst rename to docs/modules/feo/feo_time/docs/index.rst index b023149523..6e8705d4ae 100644 --- a/docs/features/frameworks/feo/modules/feo/feo_time/docs/index.rst +++ b/docs/modules/feo/feo_time/docs/index.rst @@ -13,8 +13,15 @@ # ******************************************************************************* -Component Documentation: feo_time -################################# +feo_time +######## This component will be replaced by or become a wrapper of the interface `mw::com` provided by the feature "Time". In the latter case, it is planned to be integrated into the component feo (see :ref:`comp_doc_feo`). + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/features/frameworks/feo/modules/feo/feo_log/docs/index.rst b/docs/modules/feo/feo_tracing/docs/index.rst similarity index 88% rename from docs/features/frameworks/feo/modules/feo/feo_log/docs/index.rst rename to docs/modules/feo/feo_tracing/docs/index.rst index f828328150..2bfa8352c9 100644 --- a/docs/features/frameworks/feo/modules/feo/feo_log/docs/index.rst +++ b/docs/modules/feo/feo_tracing/docs/index.rst @@ -13,8 +13,15 @@ # ******************************************************************************* -Component Documentation: feo_log -################################ +feo_tracing +########### This component will be replaced by or become a wrapper of the interface `mw::com` provided by the feature "Logging". In the latter case, it is planned to be integrated into the component feo (see :ref:`comp_doc_feo`). + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/modules/feo/index.rst b/docs/modules/feo/index.rst new file mode 100644 index 0000000000..045db16bf2 --- /dev/null +++ b/docs/modules/feo/index.rst @@ -0,0 +1,33 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + + +feo Module +########## + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index + +Components +========== + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :glob: + + ./*/docs/index diff --git a/docs/modules/index.rst b/docs/modules/index.rst index 6dc626e889..e63904f9fc 100644 --- a/docs/modules/index.rst +++ b/docs/modules/index.rst @@ -12,11 +12,17 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -.. _modules_template: +.. _modules: -Module -====== +Modules +======= + +.. note:: + For now, we store the modules documentation in the modules tree, because multi-repo docs are not yet supported. + Once this support becomes available it will be moved to the right repo. .. toctree:: :maxdepth: 1 :glob: + + ./*/index diff --git a/docs/modules/logging/docs/index.rst b/docs/modules/logging/docs/index.rst new file mode 100644 index 0000000000..439678c101 --- /dev/null +++ b/docs/modules/logging/docs/index.rst @@ -0,0 +1,31 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. mod_view_sta:: Logging + :id: mod_view_sta__logging__logging + :includes: comp_arc_sta__logging__logging + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + + +Module Documents +================ + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/modules/logging/index.rst b/docs/modules/logging/index.rst new file mode 100644 index 0000000000..84a6396a16 --- /dev/null +++ b/docs/modules/logging/index.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Logging Module +############## + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index + +Components +========== + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :glob: + + ./*/docs/index diff --git a/docs/features/communication/modules/logging/index.rst b/docs/modules/logging/logging/docs/architecture/index.rst similarity index 83% rename from docs/features/communication/modules/logging/index.rst rename to docs/modules/logging/logging/docs/architecture/index.rst index 65e65f6a0b..5f0882f82f 100644 --- a/docs/features/communication/modules/logging/index.rst +++ b/docs/modules/logging/logging/docs/architecture/index.rst @@ -12,21 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Logging Module -############## - -.. mod_view_sta:: Logging - :id: mod_view_sta__logging__logging - :includes: comp_arc_sta__logging__logging - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_module(need(), needs) }} - Component Architecture ----------------------- +********************** .. comp_arc_sta:: Logging :id: comp_arc_sta__logging__logging diff --git a/docs/modules/logging/logging/docs/index.rst b/docs/modules/logging/logging/docs/index.rst new file mode 100644 index 0000000000..6ef0c542a2 --- /dev/null +++ b/docs/modules/logging/logging/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_logging: + +logging +####### + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/features/communication/modules/os/index.rst b/docs/modules/os/docs/index.rst similarity index 89% rename from docs/features/communication/modules/os/index.rst rename to docs/modules/os/docs/index.rst index 3191590cd1..b6d9e93318 100644 --- a/docs/features/communication/modules/os/index.rst +++ b/docs/modules/os/docs/index.rst @@ -12,8 +12,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -OS Module -######### + .. mod_view_sta:: OS :id: mod_view_sta__os__os @@ -25,11 +24,9 @@ OS Module {{ draw_module(need(), needs) }} -Components -========== +Module Documents +================ .. toctree:: + :maxdepth: 2 :titlesonly: - - libc_component_architecture - message_passing_architecture diff --git a/docs/modules/os/index.rst b/docs/modules/os/index.rst new file mode 100644 index 0000000000..ef8feffd25 --- /dev/null +++ b/docs/modules/os/index.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +OS Module +######### + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index + +Components +========== + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :glob: + + ./*/docs/index diff --git a/docs/features/communication/modules/os/libc_component_architecture.rst b/docs/modules/os/libc/docs/architecture/index.rst similarity index 98% rename from docs/features/communication/modules/os/libc_component_architecture.rst rename to docs/modules/os/libc/docs/architecture/index.rst index c4fa04a805..4a0094d9c9 100644 --- a/docs/features/communication/modules/os/libc_component_architecture.rst +++ b/docs/modules/os/libc/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -libc -==== +libc Component Architecture +*************************** .. comp_arc_sta:: libc :id: comp_arc_sta__os__libc diff --git a/docs/modules/os/libc/docs/index.rst b/docs/modules/os/libc/docs/index.rst new file mode 100644 index 0000000000..8031df5cd1 --- /dev/null +++ b/docs/modules/os/libc/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_libc: + +libc +#### + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/features/communication/modules/os/message_passing_architecture.rst b/docs/modules/os/message_passing/docs/architecture/index.rst similarity index 95% rename from docs/features/communication/modules/os/message_passing_architecture.rst rename to docs/modules/os/message_passing/docs/architecture/index.rst index 6f0c9e354b..8ddfb8b33a 100644 --- a/docs/features/communication/modules/os/message_passing_architecture.rst +++ b/docs/modules/os/message_passing/docs/architecture/index.rst @@ -12,8 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Message Passing Component -========================= +Message Passing Component Architecture +************************************** .. comp_arc_sta:: QNX::Message Passing :id: comp_arc_sta__os__message_passing diff --git a/docs/modules/os/message_passing/docs/index.rst b/docs/modules/os/message_passing/docs/index.rst new file mode 100644 index 0000000000..62f79709a8 --- /dev/null +++ b/docs/modules/os/message_passing/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_os_message_passing: + +message_passing +############### + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index diff --git a/docs/modules/tracing/docs/index.rst b/docs/modules/tracing/docs/index.rst new file mode 100644 index 0000000000..e414f228a0 --- /dev/null +++ b/docs/modules/tracing/docs/index.rst @@ -0,0 +1,31 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. mod_view_sta:: Tracing + :id: mod_view_sta__tracing__tracing + :includes: comp_arc_sta__tracing__tracing + + .. needarch:: + :scale: 50 + :align: center + + {{ draw_module(need(), needs) }} + + +Module Documents +================ + +.. toctree:: + :maxdepth: 2 + :titlesonly: diff --git a/docs/modules/tracing/index.rst b/docs/modules/tracing/index.rst new file mode 100644 index 0000000000..818a5adb76 --- /dev/null +++ b/docs/modules/tracing/index.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Tracing Module +############## + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + ./docs/index + +Components +========== + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :glob: + + ./*/docs/index diff --git a/docs/features/communication/modules/tracing/index.rst b/docs/modules/tracing/tracing/docs/architecture/index.rst similarity index 84% rename from docs/features/communication/modules/tracing/index.rst rename to docs/modules/tracing/tracing/docs/architecture/index.rst index e946160387..87b3ade9f0 100644 --- a/docs/features/communication/modules/tracing/index.rst +++ b/docs/modules/tracing/tracing/docs/architecture/index.rst @@ -12,21 +12,8 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Tracing Module -############## - -.. mod_view_sta:: Tracing - :id: mod_view_sta__tracing__tracing - :includes: comp_arc_sta__tracing__tracing - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_module(need(), needs) }} - Tracing Component Architecture -============================== +****************************** .. comp_arc_sta:: Tracing :id: comp_arc_sta__tracing__tracing @@ -35,12 +22,24 @@ Tracing Component Architecture :status: valid :implements: logic_arc_int__tracing__tracing + .. needarch:: + :scale: 50 + :align: center + + {{ draw_component(need(), needs) }} + .. logic_arc_int:: Tracing :id: logic_arc_int__tracing__tracing :security: YES :safety: ASIL_B :status: valid + .. needarch:: + :scale: 50 + :align: center + + {{ draw_interface(need(), needs) }} + .. logic_arc_int_op:: Trace :id: logic_arc_int_op__tracing__trace :security: YES diff --git a/docs/modules/tracing/tracing/docs/index.rst b/docs/modules/tracing/tracing/docs/index.rst new file mode 100644 index 0000000000..462b861203 --- /dev/null +++ b/docs/modules/tracing/tracing/docs/index.rst @@ -0,0 +1,27 @@ +.. + # ******************************************************************************* + # Copyright (c) 2025 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +.. _comp_doc_tracing: + +tracing +####### + +Component Documents +=================== + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + architecture/index From 886e9eabab5aa7314996778c59940f262ee43749 Mon Sep 17 00:00:00 2001 From: "markus.schu" <markus.schu@accenture.com> Date: Thu, 24 Jul 2025 14:47:55 +0200 Subject: [PATCH 095/102] change issues templates to new version from process description the latest versions from process_description for 1-bug and 2-improvment are added prepare PRM Plan for changes after new templates are introduced --- .github/ISSUE_TEMPLATE/1-bugfix.yml | 106 ++++++++++++++++++ .github/ISSUE_TEMPLATE/2-improvement.yml | 52 +++++++++ .github/ISSUE_TEMPLATE/bug_fix.md | 13 --- .github/ISSUE_TEMPLATE/config.yml | 14 +++ .github/ISSUE_TEMPLATE/improvement.md | 11 -- .../problem_resolution.rst | 24 +--- 6 files changed, 178 insertions(+), 42 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/1-bugfix.yml create mode 100644 .github/ISSUE_TEMPLATE/2-improvement.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_fix.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/improvement.md diff --git a/.github/ISSUE_TEMPLATE/1-bugfix.yml b/.github/ISSUE_TEMPLATE/1-bugfix.yml new file mode 100644 index 0000000000..b23d6ae149 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bugfix.yml @@ -0,0 +1,106 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +name: Problem Report +description: Issue to track a bug +title: "Bug: Your bugfix title" +labels: ["codeowner_review"] +body: + - type: markdown + attributes: + value: "## <ins>Bug Ticket creation</ins>" + - type: textarea + attributes: + label: Description + description: | + Description of the Bug + Root cause / Impact / Notification required? + validations: + required: true + - type: textarea + attributes: + label: Analysis results + description: | + Documentation of the analysis results + validations: + required: true + - type: textarea + attributes: + label: Solution + description: | + Documentation of the solution + Link to Pull Request containing the solution + validations: + required: true + - type: dropdown + attributes: + label: Error Occurrence Rate + options: + - Single Event + - Sporadic + - Highly Intermittent + - Reproducible + - type: textarea + attributes: + label: How to reproduce + description: How to reproduce? + - type: textarea + attributes: + label: Supporting Information + description: | + During which operational state did the issue occur + Observations / Screenshots / Traces + validations: + required: false + - type: dropdown + attributes: + label: Classification + options: + - minor + - major + - critical + - blocker + default: 0 + validations: + required: true + - type: dropdown + attributes: + label: Affected Version + options: + - pre-0.5 + - 0.5 + - 1.0 + default: 0 + validations: + required: true + - type: dropdown + attributes: + label: Expected Closure Version + options: + - 0.5 + - 1.0 + default: 0 + validations: + required: false + - type: checkboxes + attributes: + label: Category + options: + - label: Safety Related + - label: Security Related + - type: textarea + attributes: + label: ASIL classification + description: Add ASIL classification, e.g. ASIL_B or ASIL_D + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/2-improvement.yml b/.github/ISSUE_TEMPLATE/2-improvement.yml new file mode 100644 index 0000000000..fa14031a1d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-improvement.yml @@ -0,0 +1,52 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +name: "Improvement / Task" +description: Issue to track a improvement / task +title: "Improvement: Your Improvement title" +labels: ["codeowner_review"] +body: + - type: textarea + attributes: + label: What + description: | + - Goal of the Improvement / Task + - If Req/Architecture is affected, the template of + [Change Management](https://eclipse-score.github.io/process_description/main/process_areas/change_management/guidance/change_management_impact_analysis_template.html) needs to be used + validations: + required: true + - type: textarea + attributes: + label: How + description: Details on implementation approach + validations: + required: false + - type: textarea + attributes: + label: Estimates for realization + description: | + - Estimate the effort, resources, risk for the realization + - Impact to users of the feature + validations: + required: true + - type: checkboxes + attributes: + label: Category + options: + - label: Affects Detailed Design + - type: checkboxes + attributes: + label: Requirements / Architecture + options: + - label: Requirements / Architecture are not affected by this change? + required: true diff --git a/.github/ISSUE_TEMPLATE/bug_fix.md b/.github/ISSUE_TEMPLATE/bug_fix.md deleted file mode 100644 index 43ba081bc3..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_fix.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: Bugfix -about: 'Issue to track a bugfix' -title: 'Bugfix: Your bugfix title' -labels: 'codeowner_review' -assignees: '' - ---- - -> [!IMPORTANT] -> Make sure to link this issue with the PR for your bugfix. - - diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..d8944ceeaf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/improvement.md b/.github/ISSUE_TEMPLATE/improvement.md deleted file mode 100644 index fd2c17193e..0000000000 --- a/.github/ISSUE_TEMPLATE/improvement.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: Improvement -about: 'Issue to track a improvement' -title: 'Improvement: Your improvement title' -labels: 'codeowner_review' -assignees: '' - ---- - -> [!IMPORTANT] -> Make sure to link this issue with the PR for your improvement. diff --git a/docs/platform_management_plan/problem_resolution.rst b/docs/platform_management_plan/problem_resolution.rst index 9c4c4c553b..a86cb7834d 100644 --- a/docs/platform_management_plan/problem_resolution.rst +++ b/docs/platform_management_plan/problem_resolution.rst @@ -16,6 +16,7 @@ :id: doc__platform_problem_resolution_plan :status: draft :safety: ASIL_B + :security: YES :tags: platform_management :realizes: PROCESS_wp__prm_plan @@ -66,15 +67,19 @@ used to create a problem report including required attributes as defined in the :need:`Problem Process Requirements <PROCESS_gd_req__problem__attr_uid>`. Therefore the Problem Template :need:`PROCESS_gd_temp__problem__template` shall be used. +.. note:: + The template is automatically included in the ISSUE from type **BUG** by the creation. + .. figure:: _assets/score_problem_resolution_overview.drawio.svg :width: 100% :align: center :alt: Problem Resolution Overview +The content below must be updated after v1.1.0 of Process_Description is released. Problem Resolution Attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:need:`Problem Process Requirements <PROCESS_gd_req__problem__attr_uid>` are implemented as follows: +The Problem Problem Resolution Process Requirements are implemented as follows: :need:`[[title]] <PROCESS_gd_req__problem__attr_uid>` is identical to the ISSUE number. @@ -141,23 +146,6 @@ ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For * - blocker - ``blocker`` -:need:`[[title]] <PROCESS_gd_req__problem__attr_category>` is defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For S-CORE labels are defined as: - -.. list-table:: Problem Categories - :header-rows: 1 - :widths: 15,85,15 - - * - Category - - Description - - Infrastructure - * - User - - Created by any user or :need:`Contributor <PROCESS_rl__contributor>` to report potential identified problems - - ISSUE with type BUG - * - Bug - - Created by :need:`Contributor <PROCESS_rl__contributor>` to report problems found during verification - - ISSUE with type BUG and with label ``<test level>`` - :need:`[[title]] <PROCESS_gd_req__problem__attr_safety_affected>`, :need:`[[title]] <PROCESS_gd_req__problem__attr_security_affected>` are defined in the description part of the From ae81e6e9158d90b4145198eef76af6539dd01393 Mon Sep 17 00:00:00 2001 From: "markus.schu" <markus.schu@accenture.com> Date: Fri, 25 Jul 2025 08:46:47 +0200 Subject: [PATCH 096/102] update problem resolution plan update plan according new process description version for problem resolution consider new issue template 1-bugfix set blank issue enabled to true Resolves: #1309 (partly) --- .github/ISSUE_TEMPLATE/config.yml | 2 +- ...score_problem_resolution_report.drawio.svg | 4 + ...blem_resolution_workflow_simple.drawio.svg | 2 +- .../problem_resolution.rst | 107 +++++++++++------- 4 files changed, 70 insertions(+), 45 deletions(-) create mode 100644 docs/platform_management_plan/_assets/score_problem_resolution_report.drawio.svg diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d8944ceeaf..bb96199601 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -11,4 +11,4 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -blank_issues_enabled: false +blank_issues_enabled: true diff --git a/docs/platform_management_plan/_assets/score_problem_resolution_report.drawio.svg b/docs/platform_management_plan/_assets/score_problem_resolution_report.drawio.svg new file mode 100644 index 0000000000..93e265cdc5 --- /dev/null +++ b/docs/platform_management_plan/_assets/score_problem_resolution_report.drawio.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than diagrams.net --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1185px" height="173px" viewBox="-0.5 -0.5 1185 173" content="<mxfile host="Electron" modified="2025-07-25T05:26:23.525Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="Xt7NfW4g5YwOkLu7FKAw" version="20.3.0" type="device"><diagram id="yk6BuyGx8g93CQDW87nx" name="Page-1">7XvZrqtKkOXX3MeSmIdHYxswYMDM8MY8zzNfX5l7OPdelUpqdUutkrqPzt7bTiBJIiNWrBWZ/IXf20OYwqF490na/IUhyfEX/vgLw1ACw/6C/5Hk/G5hafq7IZ/K5OekvxvM8kp/GpGf1rVM0vlfJy593yzl8O/GuO+6NF7+1RZOU7//+7Ssb/591yHM0//SYMZh819b3TJZiu9WhkT+bhfTMi9+74wiP0fa8Pfkn4a5CJN+/0cT/vwLv099v3x/ao972kDj/drl+zr+vzn6Z2BT2i3/KxckUXeFbC0jOEXqvZPd/mNp/uOnly1s1p8H/hnscv5aAIx7gB/L9stU3JZOSwkMpIRR2uj9XC5l34HjUb8sfQtOaOABLozrfOrXLrn3TT+B40mahWuz/KOHW1Pm8MqlH0BrOA/fE5iVRwrGzH3d8Pbbivy2wK7CJfwLv31/xfihy//C7qXDacaOyELe38A/1bSLp53fbpwMv97n+80Hf7k3qlo2bLl5qmkgr9s0EzH1gQ1G97FRDpx7VPvG+J+v06T4WQTxfrs95jf4Sj9ucbKNArjgXjOmbXCOWKR0gpLdkwbW5JjsKDFLVdq1qEQkqCtHKYXSM0fr1ZBG8lo6aZs9f0YM+Wk6tRx6fFN6AYvjGXvitcrGKMleq2Dp75hjwNMx3QC6FcFPfHTg+zp3uKbRB2hgRRI06IkrJXfz+6HAsG4G9qKz/fnzndOfzxv3/flxs3fj83PgxnAfjv/98jjAR/vva+z/SdfsDoX0/bAj399ftx48t8LnpX0mwA6BPmNednM9tYpTPVUIhidJIUTD4YWUptRFHi7mr/7XPgJagstDf0HoooMfXyO0o9hcZjy3bHBk7EHc5Z+b59zq6+vSCRY7jKWhtPUnREXU8mdX9hq34sPNOyMziE8DDAX2k59pc9sC8A1ji2P4vIVM7wKNy4lMPlCUPmX+UZAY+mODm5dVnQhnNlJadDwDpGrBtZYsFuYiWYVuVdsK57lW2C3BYLcbH641aEoUY8Yj2nKNN4qHmb5zwhm/G9AFnqecdAuD/AgzCbc3MeDBhZ4RKXUTo5zmEr2tnEiida7RI6mudVtpTTzBGAp0N6R9VfowT+IO7hJF48Xn36PF3zgYHD/xH75ko1eCU49BXDQ8pkMKXIdGcbICNH6MhKs0VzPdziy/Jea98NfakJuTmQVxcj226PETpgIwKl5rluej2BmZe3dW4LMwpmMyBL/htHQPFvzGc/nkzxF8kjv1+7IEDVKId4pQfGosegmmP9Vn6Ox9nCbLjycRAo0x29uRHIpZH4E/8lu2R9J00W5wyXSSUg69MQJWIYQz6VeMMJS735r+9nAmFpr4RJcFJdPy8I9XZxXnwDq+2lpoNQKYYpR58ZEEjmr15GZ4EiyLd6IOZ5OAcyjZrLTtTy5Y3RH1dBqfJx3DB7/44BMZpz6AbM7dpNvceiq84B92RtIzM/dFwA2Te9XlHRztLvJ0pg4RzowAHnQu/oqt2SeL1AXrdiJRaam43dH8trhgAFm2dsZIsDH4I70rmpnfF+X7AxKprDC3mSKPjaVjhUI5ryZI7rdseF3BTnd/PP+xifSE00Eyzh3mnajUYhMPpx9JmpNlRlMLNSRiO/82htaAkAqJEkW8VvvTWZEpnU3JPnrorwalvdTLEW688rqHzBsB80VWA3t8zyScX3NAE/wej+aR1OYSig8DHZZRAy4zT4IVrI2d6C27bY+K7amUyHm31cXMbPTmTnfj6TgQBzwvyARzSBXQ480CLYmzZSyqdac/uOM2DdbH6k5z3Fw6fjmoS6f9YNtKQ8psNVk3bWVs6GzYBCZfsZqLHc/FZlcsCrIwgUiDxuBXhWUvxln6x8JqnXUVpOHSDlWl1ttl7toXCHBd52FH6PeOfIEONwpVmik5NpcfRMz+inUZAnhFZNCnI/DDQkOBHyplSWFeXQuGwcvFrsU9YjSmjTF2uqo4kKae5lZp5Lk1BuJmy01gJisdkuHJNiBBcBmMmv1E0Tpim0vMstZpZHyvBNwa3LvxbPzp7Nwqy0yS2nSHzSaYZrJmQ3BGh4O12Gu40P4bzQIqVLz2AWarOaGDvvNv3HpyIOnyloF3E8AgFI68rQxHqqHVg3jNrYvFl4VOVL4y83tT7LkBOuDfhgTOiCr8dVuzRcYnbAp6iu+I4fYyP0L7msHU++3syejwZFZPjVIc0Ijq6LsrXqLl3V70I2u3fnhSiVa6aouTeREvaMF7oSrUdZi86nm7Nj5TKOFyFhCxE97LPLJaLD9J5WEPUmOOIFhLY5/pi40NyR4BO7GaLzSpluY8gnexqmSiXIO9ek5BMm/Je5aFp6AbcrJXQpK9B3wmMfrewHCAohdT7haSSFs2qhN0aGMIeb8KJvCxxvAoYYuNTvT+uihP73C62LcPOpKRAo0K7S9PqIO1WaNTqzdqLq22F4qEbhgire7S/Dm4mJd2l0dDN8xpF49UpIUukq1LFIQzFi6cbZDxmpqq3FgatlYGnMyQStUVGclHwNZh2pDssPVzVSC01G7e1G+YXiWPi10XA2PJCXta9zNDu7QlWaNXBZrZXkio3rOM+cmehAPhDvgJp0JOMtSnYYlS+6Bl4FeduawgDfCfm9ZWIxZibdntSKqdg1Adp3fciGbugqyo9+F1E72TfHbBbOpzjJP8vWJWJtXFBQ8QKi4z0Vqw0z8GnGkxy12bCBoqXTZKYQy1PsYr4NuJXbySUyRoZRhHJ5tIAhJuLcdb2cYw9U3zLqIEIKWjJOPSMMZYT55gBvE8YqvPbDk6tZQUY38uXhYC86arZa6B3rrn8ITRdHX0tBjw7u8kbbkyeNfv+32ayWSdW/7+DV++NmGpt6X6ClCHl15kfZ3ZzpcwB0Syoy+YVhHwPJZ8t5Edqy2R9O7sZa7X3BGLzVn8mK9g7jZdbJcplz9F1VA0+cnUQPUykzr0k4zn+p7KPO3t4Va+7OBVm65ETk+IN+ARN5KR+fnJEPSy4hbo7MHNZqpF7zZ5YBLo9aPrHn6usxcVn5dfewpJoT2yPraWaTN3RlcGBJDr6Q6IUJ4/p69H4xo5npoXREXgKdU1s1eQWv07i94ZaETJZYUR/ygQ5CMoYlWij6K3IYVAsKiLkG92pxToQVDiZZajS2vhImzGKfleR+MQrOiQtRlXEy3/RuK+bN7uzSu5S/WZzqK1YZdh+xErMGNqyW38xu91p2tpF9Hn5acKC0he6ypyu0D6jWzbdp+rSDEQ60ENFuoQfVMyKwG5xg4MnnvdeW4kBC81gPGjt1MW4UZHxQytqpJ3UnujmrP74j0cdmjq8eSYA3QANsuyLeX1KzFXNojscajv1qpzzYmGrIuw29OC4Gb1iKthFwtyF3bIPfQdPhv1kMLlzKY+bJwqANn8CA0xNlaFTO0noH0ftMMBH+ZWWaOckU1DVl/DiSaLDQ4jRTyfuufLMpEHcQZ00TOeIjwmv5Ye63vTnP2qDqWjvIIliJsw2AoVL6F2Wcg1lDJ+eJBpIDcZlfo9NDVHFQJiferz3A0aV3HplTZVW7x+2EeePrRFfeowphAQEyVqXBNGfXEQC/JDw7m3JkZJixdm0caZn9tzVNy3gyQvBHK2jHBF6fK+zmwvlmLVFZ+R1VOYdZpUb0dz8TM4o/ymH+y+62TRKeyOV3U5cQ/II2WmdSWkmAzHHoVCciMJaUEMH+31RHQZEtAQQwtCPsm9wfGE/ArsFZuxTHfhTJVwGFzKqG8jiccsW6TPhwweBaOONoWmMxuuE2AMfHM/SV9SdxTH8A+mR4btyJ7SUGe/0tR2o2f9vNOA0WIEblG9T/fpOMTuZxvR8UiCUyuSO/DKuVMac+2C9xqiMWE9r+YKJG3+ON3sLSwx0j6LgmhYwA0rMKwH1ZYzwr7D6N7uQTNi09GsWmoA6sAXBw5CLLYUyj6fP7FTemF8r9WAQRAEJLxXi4Rs9+JbfFpLiuXwOvzkdp0/R1eV6toMridWLt7kD5im6WbovagiprKieofIWvQvA5VsCh9H8rmCDNrMNFcdMmD7fCW9F5ny7Iykt2VgZuYb25AK9Mq+ytWSOksHEOgL+A9zzxU7S8viMaiZZYSZQYVl+VEFw3tO9Dhq82va2pKB/YSURi8vykI73Qyow7pf7oxEg/fF21M61kyHXtrzDDO1ldFzhRzpiZSqNKTHwByOJTd3WM7gpDunDtJ7uA5orpWkZTiPhxY2UDDYeLBZ2yxiDsL29QCP8OBxZ7uCKZmkZKXg928fXxViAak7hOLaWnGxkeot52QEuo8vj/bSFhFElO7Gs7g4HrfxfeNtpjVB29P+Ya5T9+SpKi5HQ6qb6tWf2iRMh2fRA04b19AvOpY8pnB/84/JCj7nPWEDVaMaS9nQqzMnhNXPoEfPR1dVaYva4+d1pw6kbVJcGZByc0N23cAN6cHgs2cIwhYNdv25ugblQH57hYa36Q9+xhZuMFJIgmdydKFJlABgyxWFcJgL0n0CvzoSxnoRmQ5gu2fPIdUoZAu247xrQRBP9T1TrElrzCGTFbbfAdmp20ewMvS5CeKAsn6tPN4Dfh9wQ/ZbS/+QcWeSQKb8aC1GGl3UEaOvjGBW+KxXun8m3eUfjJ+m9zskJBGegPTkSw5OPxRlN7PtM7VOZQZbS81ZsKh4mxPR+ZHl51J/Eelcn9vnTYFZ4ZPw04SaB6GJ/ezq5tKhonzCUojMyrVp4pJ9mrjtcGvNyY4XLbiLYPkidJapQvqGoM3DYuLbwhqI2y1Rh+gFyZIcP1G0SbwAU3EBwmq9o4ameODeumbzc5WbSTezlUqzt+tGL2S6UaYL+cAAMyC1g9n69oaL1odVGUC6TZYunhLODNnmqSw946tLAa4IoUOhzhBN6bYRHD5T5ww9qVBP44UkNUVHe+56pvSsm87QZcUpCUoKW+anmvO8FWRMZM5kwbRJ+PKM0TcSm9dVz7YZ0oDHB9KML0L/SNhlgPo9Y0RZop0Br2+A02wgOXYj8bmGQfR6dUFFlsQhaNtHB3379pRenHn4vduM4+ZMQBsDcm7TlPnQF6RRnUPrqr1+IhJUgrricbMDhpEAarali9xZGFvU6wSUJxwIq7+3rXyADAywf04ZLoFUIlAebNJ2/eJ1Cg+YSfzNOQgeMnA/R+TXcnlowc2Qa3ZXlF1rPDpZIrecQAdz44XJWtQ90cTagi0WzXBICoPd4j6z+77LY7u+0FV5oKvQTm2Tv3HLB3wCz4AikNqzbl4EhRUuhZNZtdEhNjXqWoV5FswURjypDqagFsTGeoQgBMNdzmNKZG2jHynI796UdlZ+UEd5W3Ps1xB5FiL7ALNO1kwAbfndctb+JevJlMOwfOILEMpMRuLDM11wmuVWEP9hrD727/AhxICQRTSkknIcHYPsXfndXOnkDAGO5zR9qtXijEH9jtvkRa68Rdbptd7nzYna6sZKkHdnE0YTTdl76nYba1eGdYgPLEvthGlDpGvLgm6ErPI813vOj9JvgAzkSQYGrNvHqmgCL+LTLMRu7GBIz9NAqXF57JIpGJczolM0BM9RXE9HbZbPvYQpfWkQ5UAPgH25N6Lhvo+WfGF61j7XgKBndrKpLpQ7m63SEc3EZZ1fnRCpLjMilKXPC0H5ckPN422Pnq3iCQ+yXF5OqlR4BtXXh2FJlYcquqfk4hI2J1yqzxII2WMQunMIjqU2WctfUxWr4kvr+9H4DPZSeKRlMjCP0DRVLhMSjqolTUyX4UBNCGyKm6jE+4+RnlBq3hjOX2bo0SzrIex3ce02vwma9XDdi1hiYNjb5ohsknZ2HyK8WWWhsb/77JNuDg4B15jz4ZHVqzcdQOcJZ0KZFUp/boD6ZFC02fdHEmjigy1YtKzj+zPQPdmXnqOPKP7jywnE+zQuyeDDQm+0tHm9RpK4UR89Ko/8Rd1tfm5WGCTDo7UctqwuHMiLvQgZ9PPOs+7JUomO+yqs9c0GSNwmFCgWUGlmAh2V7FhoEWTluA03vXdty6Oj0U1uu9QqiOIgGS8iCF/u2RjhkU3bWRa6tclMXcm2vOZ2RasFVDgzaY9YyyRe8N79z0uJRXNw6BSz9GPsOOslYlekfj4AM+WaF0emv+0a5bLosMsLSMfyu9sE595dgdzuo3+IFTsAaVSmly1jz9nd0E409YpMCLPrGjbHAAVC7sDYohpsm83i4UKrp7QPPfkZXVuBvNmrjG7aMNNfk8c+DRKJJf69hqF8FvDhuXb/RCD83hCXVjcejazVnmWiKfIbkgCzTzA6PZ7OHmraRNIES2+7s+LRgry6/f41P+puDDBCKDchB2bg1dXW61vV3+/5b72RRGcQCevmB4qwuRFpeB4+CDIkIPiivGFlDszkLf8pR2uApX6XjJxZfFFRUyfea7799veSTPfgxShZT3MxZszAZzLLxreYwjoAc7s8P+/T30ryKISLTvoPjoEKd7SQVljcSYptGff2hdyY06h/6+3359i0SwnktwjTBclbms6lqbHn3kPPQU/X889T3SSy5Li/i/PG5/anOG/Bgv7PoZ1/P39r+zf9Zt+M/xev0Q6gefxsdobb/nvG0wu/OULh/3OV43nOMiXE6q+dOW5HX7dvXwN/hr38PXIj7vWfNYmbWIKPPx50u6ev/v9f8394DWBjCBqGA0IXdjkgVBYnAVHst59LH7m4WeJeume2vl0qOa5c2ok0HgJqR/5eKxK3D8y2+GjqB8G4lr7lutlnc9f1wee7nlLfwpnY4tO57CcZFTmRUeHJzpbaXcjkUDAFBXHsKE3gPridId1fH9KJKC9oVZKxSCU5Ik51ebdVUXkBlF3P53yBM4vgFtpl5ftfMkbPN1jvPsd1Q0kuIzeibU42S3rq5pAjHnLekLL3BqQg87tC2OIZDVWF+quR+GS4q+6IeZDSP+WhgjBGwprluzACbMtxyTdsKV694NWYZCLR0bSZ47u9Us+WIdZ1vCmNBkHEtcdnWWk33blvMwZrIqR8sRE74hHNQADGTdsR6SYBwZMM2J+VEHivNWUdPrvLXlEfcdHcY855icyeKdNFqw09HAGzdp+Po0yT0ZsSQsTYFVRoe5HB+5YDjtKUGyZAxFTECo4+y67gDstzPOEZkdaec6UfSLln3YlVvsp5G0K17+LyWKcDXI02aEAB8vw7hGl6ot/u1+BeHJ2Tvt9uYuVJNZOkvtqw3qTWlds/s1mTMAGleDq7GkQTb98jV08wdx7HofpXndD0vZMMDUgfL/8MY9mrAdZmKqTzPlzUAMZCu4r2is4pD0N6ddZJDfbF9BTgw02YwXWn7egpc+9B8tyiRQOcoBzcabr9rJfqZMSXZKo07Lu7y9bAUDI6SRT9iTpT4qsDsv/X9YCup03sCkTT9BkIwORJcu4+Q3gwRMpzGEj9TZQcaWm8u6aSdH3tmOfSYpmfWbc/s8WfNjnviZSDx6JdFmnya0CuQQSZRhOdVdYHGrIhz5uiZr7xafqd/U6jyHPLRdcG//KveMGjp8I6C0ZHSbhFPU2OKE4KF8nQQVb3Spdlg4rAgiiuJci5bi9W2s9oOynALcmT7bvoZz22DvRWtvlUcX3aJtJRay8o30bAWlKEGlCNht7drZsBlFHThMN2asCbGVVViIswIpzldvp18ZAUmkv9taJTUYjSKMnVQGIxWQtNkh4Udxv2mh3lRGNry5ue8SLcrQdxtB3ki1i3NJJlOwY5bE55mZFYAY59SItFaeot6G7gyBWyaYy/ZSmOjyR9Za6d0Ty9ZWHxIbIFrhfWWb7Pbg0siG6rPD+/cYXuZppcTsjleYUxqe+qNDnef/DNwYxXgwShKpIiNjl98tYaxJrRyTn1df2eBLj8ZJD7NZpKWkDdcCCv5cRua2eRc8m+keo2hsGrRrcQD9LFHbNJcGmFoQ8Pc/d3pRKPD+RiJYCvhONyJJC6DaMVBzVnBkpWPw3siS7jI6iN2z5790TvBo5ijUVhSZKduDuO5DEdZf07zSKywbxmXFxMqUZEwTzFIeVNQugTD3RX4EeKvrPklIzRu1OQ9lnRDBTiTYZ5/cyJpze/27kD0disXWbkLNmp0YKJlTQ2aU+GCYrjg9ZMc39FSxSwN0SIcRhx/gxEmFojATAmOURJpuLDGuqt1uo6/r7TEnHCUlhSoUKV0R91wKlVpiU2C5N0bTLZ6wZ3w71JOhAs6KIkvyDiYHrqhexSIJSHazHFyF9rB7BeXKIRFimm/lNEuCDGIvQvd0C8jDme3YCK2k18FISrUfoTSUJ1bLoXFd+pyOdt7ktt6133bBegiQ5JnNsYSyZYMOsY2gDjBUz++wb6aEVQIDBWGUIujO6mZO+9jIZzI4PYYYsXX6ItPh4An6AQwRjWdZWlY0/63G9vHdOfoQJQaWMf4dPHoa54Aq0stNaDm2O/dskAoWlr7hnB8htGKw//knJCuCmbQD43KmrZ0vGuYj8hJ+ptLAqGKfOCKcTtCRa7XxNPXegCR5/ollUITGtSsRaF+JbvEVKfQJkuM0Z7WSM3XsOssN5FpvN2sBO7OVq3tKj1RDQdwWmh0ILngcg6YsBAEXIIf/Am3wsXoZfASOnjLJ2rkGqiFSjJAAZ15TgUrMe7swsjntuA8oOFTMzJcIpaN4mZ7oa/LlMEE/vD6FHWcLiM0ikKD+OtWFiDrM9gslDva/HBLYN3J1hLqRhfC8mDM2LWe9SEM4jV0Y2ScU0ttUZnahGWisTbllg0rMOZg20B1pnvwabCnf3hjri2aF3VJ0p3UTNIgXWVeEmbTISYpx+lrVx3cqd1VmyeJNdIrs3BM7GNQmIR5KoFvxfmi+pbrw4wvSHfjaVu7O7r3xCAjIaRxe3nFSEOukQ3H+Ley/eUb//JskiWKsNnovCUypf6+vgaPj4d8aQ2zmuuob4KwmCQOfam++GvWinABFMiyleaF92GRbz3W7CMW7xaL2XiyyN6wRBhzyHfHVlYH+92w6wYNQgL2LWWhm1reRamDTowF5lxDTWaKE1mRQY6dba8EFMGaZZOI3Z4mYM9+8mKhsoG0xFcLuiRJ6cO9AvgEi0P8wuF/KM1aLUkbVqqU8cSYNQtb3yk0WHSuwmShQi4U4pnrLScVBLxY4bDCjQ6jqxMsw98TLPP12Iou2hwxw7i6Jml0y5PmChcg0y0zsZ72oKFl5kWti24C+v0Dr4Cxu2IYc3M25aELnKKHD0iHT7OAk6TPKbqrSU1q/hn9cwLs8pe3fRV2OxBsIDJOdpKP0UNnR+n9HpQMezTPAEl85WC0lfyxR+YY48q5biL6MhH/4xbm3HFziGr6iBopSycwsP6ibGNA6fyBtYyu5OcAG+KBlQ4X6p8WfNpjPaR1Y6RLye0pnVn2Mj1wfBXFNMzlCmhwF4eQiIpbHsFk47jZeEVVJMOwbs1za3tzgoSrX396FebFa2q5LKbauPZVtMSG7o9XMKOHtHgCm+Aewn5AIAxhG/NpFBvs5Bnms0ZQzqZWBqm3ZtsGSMORifLcqzlEQhVoFqMtjsoCdNXMFWs3jsyaeLsSMOQBbSqFD9ybxHXD5P+xDT60AcXhvnOvjaxOMhQbVkLUTqQilpC9l61LQMIbF/4Dmt6r+ZdrUfxwmgmtMUZZOJHWcO4aO9jo1DXARfFFqS9hoPpP7FeHC7BNBnIm8NUtbg5IO2SvE0s+lo9KzXIJPUN7odIAB4Btuhx4bna20q8E3aPR8il2R5H47vxbpu7Ke1wVxSHNHwSTYkpPWGm4xalKjJ0X9W3kliW1ceaOBloouVSjw2GpPboekzWJmn648EuyCZmaYhVlrDhCTWhg06+vyq+EbPW02Z8raEBZkAv5E5mdqB117QIEP+BKRzZDG779ChZHUe9r2UG29HTVHZUwTQkSbF+9huKXKWtg2TCojwaJuQHJCLVe4vHKebmh/Ne4nl+40h1ReFK93N3DZ+mw8jrjNLRRzuNtCGzjZ3pq6g2teET6/IMp7Fn3nRuhGfzqiuiSXWWMZdFuX8r7zvknvCuC04xWxatWB1yIuwDvWcjRz7rB18Zm0dV3ZDc2SQRjHcga3pfq5NhOmq9WGGxE1kZGZ9VDZh4zBI9qMZPCJkbL31xrIo5TzIVM+9rBwQZj445TAYDhY6C2uOGlTwyqiF+U8aEVHJCvIAY4ml0oc4gXN+C2KEjIeAppNpUAUEIgipK05w1scT6cCOXh4Go6iUsKYrVQarP0pDkYrMAE8ELRMO7qw9hQRxkxK9ntsH8SHwdP4PHryV29Raedm0WDMYwywA8WsJn3AjdmYp9zzXIGc183W1ezXjEk7dReMbtXt24mTQNhAI9QX3HmveB+ywf5opHG34q1vCmTkDYEOr+GWHW7G7XI5FB/lpG2mLh6jBgQQdCTkBKp6MjBfmmN0sWEgpUlYBlQASZt3DBB0hkCWg2o0O/9vuNMYLDfRzcjlxZfLLxKN3VXJVuspeunRJoOX2D9XkqqMfMg7REmNTORZcheVyYvSe/9bTHGjOxaHODj8qkg2B9Exrimhwz0oziw1hyj/A+MuYbm1RvC2S+vHz4sxd5U/BNg3m7tkoj05z3ht876OxStAlmgNqiuaG9Eqbp6kUha2zO6CwWlU6W6+ie59G6YXdAXsDZ9RYQWvxdtOCT4gpRwsCfEUvusllo6ySsVo7rEdW99qlC9cz9Ih0dAmsPyR2Q7SUr9ypCogz2Q2W5/xa5ryJ/LmCKp7WVrpgAjAMXdTdn8e5G4g0ERp9xEqdOkcgTpXtoukzQyFvQixQra6vg+SxdcaGPXhwk6peDYjlcpefHWvypdKRr+n7IvFeWrmKuWAyIIDij8W1F1ze8LhOlGfhSem9KYWDokg6Ii2t0ttDJFjzRp3JBfTRx7pmNaPgwm3iTLNaLlnUDutILh7qB0d/CvTHlELdubYFUDSLkAB7N+7mdKmfAYZnup8aMhGUAe0P3oIZ02U1D5005kkmltYwufk6vq1RTByt/qSsiwS0Sbrw9E0rfjISFnJrkuGX8ZjYL6i86ySFUSGpVfLqqnQtFZl7P54QLFt7GZ3c5T5euGtKboK0Lm0iwKXWHeYVIKHJFQtqAS+Lv/hGHiHehFEs6Cg8hDbjotwVjcYv5j2BX82SsNWSH11CMNlOa0oRTZPRGRkeNQl2JrouVMUtuusjzzqGuCmSPdYSWdb6TeWSoT4lLtSnYXowmFk+DBglIkEM0WoK75BGYZQOhVdzXcWpYOv1mR5VU+3Bj1pR7bodU8CFcmKK1wgvknWzV9ooyZML5DU4AJoZLpi0G3m8GkZnx9bWCZZRw5dVbcOj7ZRFPXzumoAFVOu3w9Y1s6UTjnTZpjbvqZEsRyRBz3WkG7E4yRMhz1tAcH+6nRoL7DSa54i6Wsn8FDGBP1rS5DbJO4RMNktdTvnr9t85GU4R/+/xUXV93mt//UYKF28V/q6dPWIL9yTpvzvrndnEeehj3q6ByOf67x/9xe9vBNbqdMZlXh4mMmShDwpmk4pkJvnaMLNQfyxTufhMgRvYg76wIr7iA7pb0W/jtbH0n4kes0XLMtl4SsN/2/N4Qf989/68763FUWW6RPYpPa3A9Kx1eVXgEEWS3FZDi3Yc23mSynVBCOb5KTftgHQaLqwN1aXeDoM4FAoM8oKFKas97KikLTT5oMbuKzo0nl0fCYU0n3INSahRpyXu4xYhm7BaPJJoRFGICTBwo1mBWEqB/rIav48V4NBGwGSWacNVKAqQyTTw2ldMHRO0tzB4GQcqncjvsKWupSyKp8grWDuto/DREI4HgAUPAk0hUW8UpObqHfnhIC2s1K25B0m8HFM7GFhZq6Ru9rrhk8QkNG9cSNwxGUjbVcM87N/LvbkkwuACsDBb92GicbLeCrvRyZQVYqRPruj+PZCunOP18e+au4o/54D9RU5hzkxeCxZ75HQnHqYp9WWELAmWxfXZOLZkri1BtxdTq3c9fe4YxPCreDow12g9y52p2lWL+fQw7JYoUtqMvVqkExVoFit5Amk8gb5iKNTJj1e6sLN+6CxuVZfcQqtgXdQPaynAHGyg7LDRhhPNwXRphBUaiEs9ITnxpLgJyEkJZsZYOpmlDURb9Yjqf3k8/RZ0F1xWN6gIpEfqZ9EZmg1c3XEGmZXa2lpf4mEYTS/URdJw0FwUnanvn5ZN1YAKsuOZB4ZvHHiQslLMMwX7O0463tcqyZaArMD8/URs/slPpb1TcGEjMQyTKFEAl3SdXWVsYJGmaBVA1esYEiyg8B1GOQsct4+XqmRLh634mLMPdcS9+Wgv1+GC3YKZJJfb5o4MVA92ky/H+VIfr4yPOQ9SPUi4zvVOQsoC7MmRe2Ns6SwLDA3MN7WUGz+GVf7ydjMvPfKjPrwrC3dGwFIvv+p19XDoUpP71qhKmrKpRfijUpF/b157vYg9WwX4kVNJBYqWNikJHW2qyOrWECCsRIbAweyXfBT1V1rBoq+dvc4gPnCnPG9C2ZxEDsWvPwqNgIsot/eLS6hlrMsRohvhCQGosH61fcCYRIGGwf8jovKRuwACxn174xuSX6rHtEShcRUGsccIAJDTKQ0Wj1hYsR0NzsynLvZAmC5LPNTZZIn+mFBb/uRTHWfsikm5EdvjyDS8007B4LpALqrZIZHLcOIPKDEn8uKhEQ/LyTsXUxyzdYJnm+2HuRIrXgIU5QP0j32pgru73G2qrarV3h9z16IGkQylI0bjsn2zxr2MxkUwN+XuZ+HTMvI1EfZqkYAF/e2ZYeud/qr2l+W494umQ1IWDLLMlr8+p4gLcCcOpZEw/y6mcDX7o5cxCzdFWjG5hns2kpd1lrxSiHnDpf+GBzv5G7/cjOVhtI7TWnu7kAsndcn+EuDK8BNFE3uYU4TWa06ZQx9SzLnVmZ/N+VVaSDaJyKp6TwtiiMd5AWkRWYk90tlt9555ZjSAYi7jUbCiODV45nw3GsMRejm4EIYpMU1A7c1LRkyeJSoKv5F5/G1AjmC7/WlFajlAfePXypAk+fufpzsugjscQ3uHuj4m2h4c1IHiM2JtPvTXc3ue2wQQAk7WndxcYsw5F4Id9DBRN0RNrtiUB1K873mzcuI2vDodO0rk0pd6Afw3o1bA13OHbIIYEiXiKOhSUMWT28o8xbVVY5snfPyMFIjN3Pto0tO3CINoDsPM6E6gHBBp/IddVU7U9kSiD/tJqXONdlAB07fkQQptfodjkX6H+KBybwuFIR5gB76QKVLEgK30pd+NEH7vl36vMQNColZFhyniJs6wMqEaQvt7dZTnYCJ4t/hIO0YKko6ZpymLcZY9rev+7rK4MMUP7c+7xH+yzPL5KG+yJ0uh0mdjy4D+VFqUrYgxw6x3aLWdHxDQzjxk+vl2djb85EtQ6eKt/fvk0oLhSgkAAcDj/LnDF9Fnf7qa61met4RpFj17Mdp7d7pfCI6QJJpUS+8ppoiKouc4ezxwr3CrdolPrmpuf41kPcm5iU+IHBg+OlARIYIe2iCh8/4PdNsbDRrn82KsYDayv4w7lhZl7peeU38XHUVdVgi3JE+OGm3dffMqB/TARGtbdi3k83fMLxXqTLKG9Lnp6s7KxTyRO67CUKdO4cpdTBNZRefad3aUk2kbZ39cloef6YwgZzqsMGc4Ovz6BWAWjshh9yLCBqSX+Tm3ISXzJj8sqNYJdsx/M3yVk8m9Pm5C8117Zf5BvFRC0f90jIglvyMAXxfPndQT1TO4ytx9HfsbDod6zD56opgeE4RZs9ngVP6pQvOP+p0/pIjcoOJqBUq3zd80qufx/rRDL3u/iMWCSt/8N9vl/6RpH3qc+uDArgbqVpB5/VuF2kTXI/Bw6J3q/P68/D9fl0+vvTR2AGPfn7fea/JVAdgcrUyeHJuxHe0Jv+jrGSYZNPqdayvMcvhUM/3M/rw6n05Ie/+07yeifN53bQ0j7FghSoJWQ499vef+8HP77qvT+95vWKMoQ343FP1+zpn/eUw5/Xu/O/3T99xvQUGR+vwT9+/Xvl62/jv3jlXX8+Z8=</diagram></mxfile>" style="background-color: rgb(255, 255, 255);"><defs/><g><image x="-0.5" y="-0.5" width="1184" height="172" xlink:href="data:image/png;base64,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" preserveAspectRatio="none"/></g></svg> \ No newline at end of file diff --git a/docs/platform_management_plan/_assets/score_problem_resolution_workflow_simple.drawio.svg b/docs/platform_management_plan/_assets/score_problem_resolution_workflow_simple.drawio.svg index 924e5af851..087dbc9b5a 100644 --- a/docs/platform_management_plan/_assets/score_problem_resolution_workflow_simple.drawio.svg +++ b/docs/platform_management_plan/_assets/score_problem_resolution_workflow_simple.drawio.svg @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Do not edit this file with editors other than diagrams.net --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1230px" height="1053px" viewBox="-0.5 -0.5 1230 1053" content="<mxfile host="Electron" modified="2025-04-08T06:20:03.919Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="3QbIQfRPWAysjTjfV7A0" version="20.3.0" type="device"><diagram id="0w90vh-N4AjfHz9zUi27" name="Model">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</diagram></mxfile>"><defs/><g><rect x="140" y="720" width="420" height="140" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 790px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />closed<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="580" width="420" height="140" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 650px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />in implementation<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="300" width="420" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 370px; margin-left: 142px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />open<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="374" fill="#333333" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="440" width="420" height="140" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 510px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br />status:<br />in review<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><div style=""><br /></div></div></div></div></foreignObject><text x="142" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><path d="M 375 360 L 433.63 360" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 438.88 360 L 431.88 363.5 L 433.63 360 L 431.88 356.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="255" y="330" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 360px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[Open]</div></div></div></foreignObject><text x="315" y="364" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 310 70 L 310 165.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 310 170.88 L 306.5 163.88 L 310 165.63 L 313.5 163.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="250" y="100" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 115px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">creates</div></div></div></foreignObject><text x="280" y="119" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">creates</text></switch></g><ellipse cx="310" cy="55" rx="15" ry="15" fill="#000000" stroke="none" pointer-events="all"/><rect x="210" y="0" width="220" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 20px; margin-left: 320px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 18px;">Contributor, Committer</font></b></div></div></div></foreignObject><text x="320" y="24" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Contributor, Committer</text></switch></g><path d="M 250 212 L 230 212 L 230 345 L 248.63 345" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 345 L 246.88 348.5 L 248.63 345 L 246.88 341.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 250 172 L 370 172 L 370 240 Q 340 218.4 310 240 Q 280 261.6 250 240 L 250 184 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 200px; margin-left: 251px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Problem<br />Report</div></div></div></foreignObject><text x="310" y="204" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Problem...</text></switch></g><rect x="255" y="760" width="120" height="60" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 790px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[CLOSED]</div></div></div></foreignObject><text x="315" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><rect x="255" y="480" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 510px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[OPEN]</div></div></div></foreignObject><text x="315" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><rect x="140" y="860" width="420" height="140" fill="#bac8d3" stroke="#23445d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 930px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br />CR status:<br />rejected<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><div style=""><br /></div></div></div></div></foreignObject><text x="142" y="934" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">CR status:...</text></switch></g><rect x="255" y="900" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 930px; margin-left: 256px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[CLOSED AS NOT PLANNED]</div></div></div></foreignObject><text x="315" y="934" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 484.97 390 L 484.97 473.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 484.97 478.87 L 481.47 471.87 L 484.97 473.62 L 488.47 471.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="440" y="330" width="90" height="60" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 440 350 L 530 350" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 460 330 L 460 390" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 360px; margin-left: 441px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     No Status</div></div></div></foreignObject><text x="485" y="364" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="459" y="326" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 341px; margin-left: 494px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="494" y="345" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 375 510 L 433.63 510" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 438.88 510 L 431.88 513.5 L 433.63 510 L 431.88 506.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 485.02 540 L 485.02 613.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 485.02 618.87 L 481.52 611.87 L 485.02 613.62 L 488.52 611.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="440" y="480" width="90" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><path d="M 440 500 L 530 500" fill="none" stroke="#82b366" stroke-miterlimit="10" pointer-events="all"/><path d="M 460 480 L 460 540" fill="none" stroke="#82b366" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 510px; margin-left: 441px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />Todo</div></div></div></foreignObject><text x="485" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="459" y="476" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 491px; margin-left: 494px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="494" y="495" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 315 680 L 315 690 L 640 690 L 640 750 L 733.63 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 738.88 750 L 731.88 753.5 L 733.63 750 L 731.88 746.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 315 680 L 315 690 L 640 690 L 640 880 L 733.63 880" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 738.88 880 L 731.88 883.5 L 733.63 880 L 731.88 876.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 255 665 L 220 665 L 220 915 L 248.63 915" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 915 L 246.88 918.5 L 248.63 915 L 246.88 911.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="255" y="620" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 650px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[OPEN]</div></div></div></foreignObject><text x="315" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 374 650 L 432.63 650" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 437.88 650 L 430.88 653.5 L 432.63 650 L 430.88 646.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 483.97 680 L 483.97 753.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 483.97 758.87 L 480.47 751.87 L 483.97 753.62 L 487.47 751.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="620" width="90" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><path d="M 439 640 L 529 640" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/><path d="M 459 620 L 459 680" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 650px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     In Progress</div></div></div></foreignObject><text x="484" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="458" y="616" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 631px; margin-left: 493px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="493" y="635" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 255 510 L 120 510 L 120 930 L 248.63 930" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 930 L 246.88 933.5 L 248.63 930 L 246.88 926.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 380.37 790 L 439 790" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 375.12 790 L 382.12 786.5 L 380.37 790 L 382.12 793.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 529 790 L 550 790 L 550 650 L 535.37 650" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 530.12 650 L 537.12 646.5 L 535.37 650 L 537.12 653.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="760" width="90" height="60" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><path d="M 439 780 L 529 780" fill="none" stroke="#9673a6" stroke-miterlimit="10" pointer-events="all"/><path d="M 459 760 L 459 820" fill="none" stroke="#9673a6" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 790px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     Done</div></div></div></foreignObject><text x="484" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="458" y="756" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 771px; margin-left: 493px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="493" y="775" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 866.37 750 L 1058.63 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 861.12 750 L 868.12 746.5 L 866.37 750 L 868.12 753.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 750 L 1056.88 753.5 L 1058.63 750 L 1056.88 746.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="740" y="720" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 750px; margin-left: 741px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE</div></div></div></foreignObject><text x="800" y="754" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE</text></switch></g><rect x="1065" y="940" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 970px; margin-left: 1066px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PR</div></div></div></foreignObject><text x="1125" y="974" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">PR</text></switch></g><path d="M 910 620 L 800 620 L 800 713.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 800 718.88 L 796.5 711.88 L 800 713.63 L 803.5 711.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 910 580 L 1030 580 L 1030 648 Q 1000 626.4 970 648 Q 940 669.6 910 648 L 910 592 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 608px; margin-left: 911px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Change<br />Request</div></div></div></foreignObject><text x="970" y="612" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Change...</text></switch></g><rect x="1065" y="818" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 848px; margin-left: 1066px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PR</div></div></div></foreignObject><text x="1125" y="852" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">PR</text></switch></g><path d="M 830 786.37 L 830 800 L 1000 800 L 1000 848 L 1058.63 848" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 830 781.12 L 833.5 788.12 L 830 786.37 L 826.5 788.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 848 L 1056.88 851.5 L 1058.63 848 L 1056.88 844.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="1110" y="883" width="30" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 903px; margin-left: 1125px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 23px;">:</font></b></div></div></div></foreignObject><text x="1125" y="907" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">:</text></switch></g><path d="M 1191.37 750 L 1220 750 L 1220 848 L 1191.37 848" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1186.12 750 L 1193.12 746.5 L 1191.37 750 L 1193.12 753.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1186.12 848 L 1193.12 844.5 L 1191.37 848 L 1193.12 851.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="1065" y="720" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 750px; margin-left: 1066px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">SUB-<br />ISSUE</div></div></div></foreignObject><text x="1125" y="754" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">SUB-...</text></switch></g><path d="M 866.37 880 L 962.5 880 L 962.5 985 L 1058.63 985" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 861.12 880 L 868.12 876.5 L 866.37 880 L 868.12 883.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 985 L 1056.88 988.5 L 1058.63 985 L 1056.88 981.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="740" y="850" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 880px; margin-left: 741px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE</div></div></div></foreignObject><text x="800" y="884" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE</text></switch></g><rect x="785" y="800" width="30" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 820px; margin-left: 800px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 23px;">:</font></b></div></div></div></foreignObject><text x="800" y="824" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">:</text></switch></g><path d="M 25 340.5 L 35 340.5 L 35 398.5 L 45.5 398.5 L 30 417.5 L 14.5 398.5 L 25 398.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="10" y="290" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 305px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Creation</font></b></div></div></div></foreignObject><text x="50" y="309" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Creation</text></switch></g><rect x="10" y="440" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 455px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Analysis</font></b></div></div></div></foreignObject><text x="50" y="459" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Analysis</text></switch></g><path d="M 25 502.5 L 35 502.5 L 35 560.5 L 45.5 560.5 L 30 579.5 L 14.5 560.5 L 25 560.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="0" y="580" width="100" height="50" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 605px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Initiate and <br />Monitor<br /></font></b></div></div></div></foreignObject><text x="50" y="609" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Initiate and...</text></switch></g><path d="M 25 642.5 L 35 642.5 L 35 700.5 L 45.5 700.5 L 30 719.5 L 14.5 700.5 L 25 700.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="15" y="740" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 755px; margin-left: 45px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Close<br /></font></b></div></div></div></foreignObject><text x="45" y="759" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Close </text></switch></g><path d="M 25 782.5 L 35 782.5 L 35 840.5 L 45.5 840.5 L 30 859.5 L 14.5 840.5 L 25 840.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 255 360 L 100 360 L 100 950 L 248.63 950" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 950 L 246.88 953.5 L 248.63 950 L 246.88 946.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1230px" height="1091px" viewBox="-0.5 -0.5 1230 1091" content="<mxfile host="Electron" modified="2025-07-25T06:30:13.928Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="sNebu8L1acWW96RK2Bt4" version="20.3.0" type="device"><diagram id="0w90vh-N4AjfHz9zUi27" name="Model">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</diagram></mxfile>"><defs/><g><rect x="140" y="720" width="420" height="140" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 790px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />closed<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="580" width="420" height="140" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 650px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />in implementation<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="300" width="420" height="140" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 370px; margin-left: 142px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />status:<br />open<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></div></div></foreignObject><text x="142" y="374" fill="#333333" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><rect x="140" y="440" width="420" height="140" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 510px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br />status:<br />in review<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><div style=""><br /></div></div></div></div></foreignObject><text x="142" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">status:...</text></switch></g><path d="M 375 360 L 433.63 360" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 438.88 360 L 431.88 363.5 L 433.63 360 L 431.88 356.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="255" y="330" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 360px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[Open]</div></div></div></foreignObject><text x="315" y="364" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 310 70 L 310 165.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 310 170.88 L 306.5 163.88 L 310 165.63 L 313.5 163.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="250" y="100" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 115px; margin-left: 280px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">creates</div></div></div></foreignObject><text x="280" y="119" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">creates</text></switch></g><ellipse cx="310" cy="55" rx="15" ry="15" fill="#000000" stroke="none" pointer-events="all"/><rect x="210" y="0" width="220" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 20px; margin-left: 320px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 18px;">Contributor, Committer</font></b></div></div></div></foreignObject><text x="320" y="24" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Contributor, Committer</text></switch></g><path d="M 250 212 L 230 212 L 230 345 L 248.63 345" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 345 L 246.88 348.5 L 248.63 345 L 246.88 341.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 250 172 L 370 172 L 370 240 Q 340 218.4 310 240 Q 280 261.6 250 240 L 250 184 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 200px; margin-left: 251px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Problem<br />Report</div></div></div></foreignObject><text x="310" y="204" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Problem...</text></switch></g><rect x="255" y="760" width="120" height="60" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 790px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[CLOSED]</div></div></div></foreignObject><text x="315" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><rect x="255" y="480" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 510px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[OPEN]</div></div></div></foreignObject><text x="315" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><rect x="140" y="860" width="420" height="140" fill="#bac8d3" stroke="#23445d" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 418px; height: 1px; padding-top: 930px; margin-left: 142px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;"><br /><br /><br /><br /><br />CR status:<br />rejected<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><div style=""><br /></div></div></div></div></foreignObject><text x="142" y="934" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" font-weight="bold">CR status:...</text></switch></g><rect x="255" y="900" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 930px; margin-left: 256px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[CLOSED AS NOT PLANNED]</div></div></div></foreignObject><text x="315" y="934" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 484.97 390 L 484.97 473.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 484.97 478.87 L 481.47 471.87 L 484.97 473.62 L 488.47 471.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="440" y="330" width="90" height="60" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 440 350 L 530 350" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 460 330 L 460 390" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 360px; margin-left: 441px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     No Status</div></div></div></foreignObject><text x="485" y="364" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="459" y="326" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 341px; margin-left: 494px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="494" y="345" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 375 510 L 433.63 510" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 438.88 510 L 431.88 513.5 L 433.63 510 L 431.88 506.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 485.02 540 L 485.02 613.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 485.02 618.87 L 481.52 611.87 L 485.02 613.62 L 488.52 611.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="440" y="480" width="90" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><path d="M 440 500 L 530 500" fill="none" stroke="#82b366" stroke-miterlimit="10" pointer-events="all"/><path d="M 460 480 L 460 540" fill="none" stroke="#82b366" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 510px; margin-left: 441px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />Todo</div></div></div></foreignObject><text x="485" y="514" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="459" y="476" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 491px; margin-left: 494px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="494" y="495" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 315 680 L 315 690 L 640 690 L 640 750 L 733.63 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 738.88 750 L 731.88 753.5 L 733.63 750 L 731.88 746.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 315 680 L 315 690 L 640 690 L 640 880 L 733.63 880" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 738.88 880 L 731.88 883.5 L 733.63 880 L 731.88 876.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 255 665 L 220 665 L 220 915 L 248.63 915" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 915 L 246.88 918.5 L 248.63 915 L 246.88 911.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 315 680 L 315 690 L 640 690 L 640 1060 L 1058.63 1060" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1063.88 1060 L 1056.88 1063.5 L 1058.63 1060 L 1056.88 1056.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="255" y="620" width="120" height="60" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 650px; margin-left: 256px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE<br />[OPEN]</div></div></div></foreignObject><text x="315" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE...</text></switch></g><path d="M 374 650 L 432.63 650" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 437.88 650 L 430.88 653.5 L 432.63 650 L 430.88 646.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 483.97 680 L 483.97 753.62" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 483.97 758.87 L 480.47 751.87 L 483.97 753.62 L 487.47 751.87 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="620" width="90" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/><path d="M 439 640 L 529 640" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/><path d="M 459 620 L 459 680" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 650px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     In Progress</div></div></div></foreignObject><text x="484" y="654" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="458" y="616" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 631px; margin-left: 493px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="493" y="635" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 255 510 L 120 510 L 120 930 L 248.63 930" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 930 L 246.88 933.5 L 248.63 930 L 246.88 926.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 380.37 790 L 439 790" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 375.12 790 L 382.12 786.5 L 380.37 790 L 382.12 793.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 529 790 L 550 790 L 550 650 L 535.37 650" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 530.12 650 L 537.12 646.5 L 535.37 650 L 537.12 653.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="760" width="90" height="60" fill="#e1d5e7" stroke="#9673a6" pointer-events="all"/><path d="M 439 780 L 529 780" fill="none" stroke="#9673a6" stroke-miterlimit="10" pointer-events="all"/><path d="M 459 760 L 459 820" fill="none" stroke="#9673a6" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 790px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><br />status:<br />     Done</div></div></div></foreignObject><text x="484" y="794" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">status:...</text></switch></g><rect x="458" y="756" width="70" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 771px; margin-left: 493px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Projects</div></div></div></foreignObject><text x="493" y="775" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Projects</text></switch></g><path d="M 866.37 750 L 1058.63 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 861.12 750 L 868.12 746.5 L 866.37 750 L 868.12 753.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 750 L 1056.88 753.5 L 1058.63 750 L 1056.88 746.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="740" y="720" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 750px; margin-left: 741px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE</div></div></div></foreignObject><text x="800" y="754" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE</text></switch></g><rect x="1065" y="940" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 970px; margin-left: 1066px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PR</div></div></div></foreignObject><text x="1125" y="974" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">PR</text></switch></g><path d="M 910 620 L 800 620 L 800 713.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 800 718.88 L 796.5 711.88 L 800 713.63 L 803.5 711.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 910 580 L 1030 580 L 1030 648 Q 1000 626.4 970 648 Q 940 669.6 910 648 L 910 592 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 608px; margin-left: 911px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Change<br />Request</div></div></div></foreignObject><text x="970" y="612" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Change...</text></switch></g><rect x="1065" y="818" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 848px; margin-left: 1066px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PR</div></div></div></foreignObject><text x="1125" y="852" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">PR</text></switch></g><path d="M 830 786.37 L 830 800 L 1000 800 L 1000 848 L 1058.63 848" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 830 781.12 L 833.5 788.12 L 830 786.37 L 826.5 788.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 848 L 1056.88 851.5 L 1058.63 848 L 1056.88 844.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="1110" y="883" width="30" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 903px; margin-left: 1125px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 23px;">:</font></b></div></div></div></foreignObject><text x="1125" y="907" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">:</text></switch></g><path d="M 1191.37 750 L 1220 750 L 1220 848 L 1191.37 848" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 1186.12 750 L 1193.12 746.5 L 1191.37 750 L 1193.12 753.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1186.12 848 L 1193.12 844.5 L 1191.37 848 L 1193.12 851.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="1065" y="720" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 750px; margin-left: 1066px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">SUB-<br />ISSUE</div></div></div></foreignObject><text x="1125" y="754" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">SUB-...</text></switch></g><path d="M 866.37 880 L 962.5 880 L 962.5 985 L 1058.63 985" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 861.12 880 L 868.12 876.5 L 866.37 880 L 868.12 883.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1063.88 985 L 1056.88 988.5 L 1058.63 985 L 1056.88 981.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="740" y="850" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 880px; margin-left: 741px;"><div data-drawio-colors="color: #333333; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(51, 51, 51); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">ISSUE</div></div></div></foreignObject><text x="800" y="884" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle">ISSUE</text></switch></g><rect x="785" y="800" width="30" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 820px; margin-left: 800px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 23px;">:</font></b></div></div></div></foreignObject><text x="800" y="824" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">:</text></switch></g><path d="M 25 340.5 L 35 340.5 L 35 398.5 L 45.5 398.5 L 30 417.5 L 14.5 398.5 L 25 398.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="10" y="290" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 305px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Creation</font></b></div></div></div></foreignObject><text x="50" y="309" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Creation</text></switch></g><rect x="10" y="440" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 455px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Analysis</font></b></div></div></div></foreignObject><text x="50" y="459" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Analysis</text></switch></g><path d="M 25 502.5 L 35 502.5 L 35 560.5 L 45.5 560.5 L 30 579.5 L 14.5 560.5 L 25 560.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="0" y="580" width="100" height="50" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 605px; margin-left: 50px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Initiate and <br />Monitor<br /></font></b></div></div></div></foreignObject><text x="50" y="609" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Initiate and...</text></switch></g><path d="M 25 642.5 L 35 642.5 L 35 700.5 L 45.5 700.5 L 30 719.5 L 14.5 700.5 L 25 700.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="15" y="740" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 755px; margin-left: 45px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;"><b><font style="font-size: 14px;">Close<br /></font></b></div></div></div></foreignObject><text x="45" y="759" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Close </text></switch></g><path d="M 25 782.5 L 35 782.5 L 35 840.5 L 45.5 840.5 L 30 859.5 L 14.5 840.5 L 25 840.5 Z" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 255 360 L 100 360 L 100 950 L 248.63 950" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253.88 950 L 246.88 953.5 L 248.63 950 L 246.88 946.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="1065" y="1030" width="120" height="60" fill="#647687" stroke="#314354" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 1060px; margin-left: 1066px;"><div data-drawio-colors="color: #ffffff; " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(255, 255, 255); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">PR</div></div></div></foreignObject><text x="1125" y="1064" fill="#ffffff" font-family="Helvetica" font-size="12px" text-anchor="middle">PR</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/docs/platform_management_plan/problem_resolution.rst b/docs/platform_management_plan/problem_resolution.rst index a86cb7834d..439df845e6 100644 --- a/docs/platform_management_plan/problem_resolution.rst +++ b/docs/platform_management_plan/problem_resolution.rst @@ -59,23 +59,28 @@ Problem Resolution Infrastructure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :need:`GitHub Issues (ISSUE) <doc__issue_guideline>` are used for managing problems and their -potential resolution. The tool is used to create, analyse, initiate and to monitor the +potential resolution. The tool is used to create, analyze, initiate and to monitor the problem reported within **S-CORE**. The next figure gives an overview, how problems are created in **S-CORE**. An ISSUE is used to create a problem report including required attributes as defined in the :need:`Problem Process Requirements <PROCESS_gd_req__problem__attr_uid>`. -Therefore the Problem Template :need:`PROCESS_gd_temp__problem__template` shall be used. - -.. note:: - The template is automatically included in the ISSUE from type **BUG** by the creation. .. figure:: _assets/score_problem_resolution_overview.drawio.svg :width: 100% :align: center :alt: Problem Resolution Overview -The content below must be updated after v1.1.0 of Process_Description is released. +Therefore the Problem Template :need:`PROCESS_gd_temp__problem__template` shall be used. + +.. note:: + The template is automatically included in the ISSUE **Problem Report**. + Use ISSUE **Problem Report** to report a detected problem in **S-CORE**. + + .. figure:: _assets/score_problem_resolution_report.drawio.svg + :width: 100% + :align: center + :alt: Problem Resolution Overview Problem Resolution Attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -117,19 +122,29 @@ and the state in the Projects dashboard view. The PR status is also used, if app :need:`[[title]] <PROCESS_gd_req__problem__attr_title>` is identical to the ISSUE title. -:need:`[[title]] <PROCESS_gd_req__problem__attr_impact_description>` is defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. +:need:`[[title]] <PROCESS_gd_req__problem__attr_impact_description>` is provided in the Description +part of the ISSUE. Add here the root cause and impact of the problem. Optionally state, who +has to be informed or notified, if applicable, e.g. Safety Manager of a feature. -:need:`[[title]] <PROCESS_gd_req__problem__attr_anaylsis_results>` is defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. +Further information can be provided in the Supporting Information part of the ISSUE. Especially +"How to reproduce" and "Error occurrence Rate" shall be documented, thus extra parts are provided +for that in the ISSUE. -:need:`[[title]] <PROCESS_gd_req__problem__attr_stakeholder>` is defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For S-CORE stakeholder use pre-defined labels -for Communities or Feature Teams (Feature Owner) (under discussion, compare -https://github.com/eclipse-score/score/issues/870) +To identify, in which version the problem occurred, use the Affected Version +part of the ISSUE. -:need:`[[title]] <PROCESS_gd_req__problem__attr_classification>` is defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For S-CORE labels are defined as: +To provide solutions, use the Solution part of the ISSUE. + +:need:`[[title]] <PROCESS_gd_req__problem__attr_anaylsis_results>` is provided in the analysis +results part of the ISSUE. State here, if the problem is accepted or rejected. Safety/Security +experts must confirm or disconfirm, if safety/security is affected is set correctly + +:need:`[[title]] <PROCESS_gd_req__problem__attr_stakeholder>` are provided in the Assignees part of +the ISSUE. In addition you can use pre-defined labels for Communities or Feature Teams +(Feature Owner) (under discussion, compare https://github.com/eclipse-score/score/issues/870). + +:need:`[[title]] <PROCESS_gd_req__problem__attr_classification>` is provided in the Classification +part of the ISSUE. Select one of provided identifiers: .. list-table:: Problem Classification :header-rows: 1 @@ -148,15 +163,16 @@ ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For :need:`[[title]] <PROCESS_gd_req__problem__attr_safety_affected>`, -:need:`[[title]] <PROCESS_gd_req__problem__attr_security_affected>` are defined in the description part of the -ISSUE using the Problem Template :need:`PROCESS_gd_temp__problem__template`. For S-CORE labels are defined to mark affected -ISSUEs: -``safety``, ``security`` +:need:`[[title]] <PROCESS_gd_req__problem__attr_security_affected>` are provided in the Category +part of the ISSUE. -Combinations of them are allowed. +Combinations of them are allowed. If nothing is selected, Quality is affected by default. +Use the ASIL classification part of the ISSUE to document the ASIL level concerned, e.g. ASIL_B. -:need:`[[title]] <PROCESS_gd_req__problem__attr_milestone>` is defined by the Milestone of a ISSUE. + +:need:`[[title]] <PROCESS_gd_req__problem__attr_milestone>` is provided in the Expected Closure +Version part of the ISSUE. Optionally the Milestone part of the ISSUE can be set. Problem Resolution Workflow @@ -164,13 +180,14 @@ Problem Resolution Workflow In general, every Problem Resolution follows the following steps: -(color is refering to the following figure: Problem Resolution Simple Workflow Overview) +(color is referring to the following figure: Problem Resolution Simple Workflow Overview) * 1. Create the Problem report (grey color) -* 2. Analyse the Problem report (blue color) +* 2. Analyze the Problem report (blue color) * 3. Initiate the implementation of the Problem Resolution and track it to closure (yellow color) * 3. Close Problem Resolution (purple color) +:need:`PROCESS_gd_guidl__problem__problem` can give additional help. **To 1. Create the Problem Report:** @@ -178,11 +195,12 @@ An ISSUE is the **ONLY** way to create and manage a Problem in **S-CORE**. The figure below shows the workflow for the simplest case of a Problem Resolution workflow. -An ISSUE with the type ``Bug`` is created in status ``Open``. -The title of the ISSUE reflects the potential problem. Further add here the -:need:`Problem Template <PROCESS_gd_temp__problem__template>` and fill it out accordingly. +An ISSUE **Problem Report** with the type ``Bug`` is created in status ``Open``. +The title of the ISSUE reflects the potential problem. Further fill out the provided template +content accordingly. -Planning is done by setting the milestone of the ISSUE accordingly. +Planning is done by setting the **Expected Closure Version**. Optionally the Milestone of the ISSUE +can be set. Problem status: ``open`` is implemented as ISSUE status ``Open`` and Projects status ``No Status``. @@ -201,30 +219,33 @@ set the ISSUE status to ``Closed as not planned``. Problem Resolution Simple Workflow Overview -**To 2. Analyse the Problem Report:** +**To 2. Analyze the Problem Report:** -The Problem Report is reviewed and analysed from the :need:`Committer <PROCESS_rl__committer>` and the +The Problem Report is reviewed and analyzed from the :need:`Committer <PROCESS_rl__committer>` and the review results are resolved by the :need:`Contributor <PROCESS_rl__contributor>`. The results -are documented in the ISSUE. As long as the information is not sufficient, the related ISSUE is kept in -status ``Open`` and Projects status ``Todo``, means ``in review``. +are documented in the ISSUE. As long as the information is not sufficient, the related ISSUE is +kept in status ``Open`` and Projects status ``Todo``, means ``in review``. If the information is sufficient and it is decided to initiate the problem resolution, the ISSUE status is kept ``Open`` and the Projects status is set to ``In Progress``. +The decision, if the problem is accepted or rejected must be documented. Safety/Security +experts must confirm or disconfirm, if safety/security is affected is set correctly. + :need:`PROCESS_gd_chklst__problem__cr_review` can help to verify whether the information is complete. In case affected parties need to be informed :need:`Technical Lead <PROCESS_rl__technical_lead>` or -:need:`Module Lead <PROCESS_rl__module_lead>` will notfiy them. +:need:`Module Lead <PROCESS_rl__module_lead>` will notify them, either updating the Assignees or +adding labels for community or feature teams. -Otherwise, if no Problem Resolution is planned, the problem is rejected. -To reject the Problem Report: Problem status: ``rejected`` -set the ISSUE status to ``Closed as not planned``. +Otherwise, if no Problem Resolution is planned, the problem is rejected. To reject the Problem +Report: Problem status: ``rejected`` set the ISSUE status to ``Closed as not planned``. **To 3. Initiate and Monitor the Problem Resolution:** :need:`Contributor <PROCESS_rl__contributor>` starts all required activities to resolve the problem. -These may include starting Change Requests or in general plannig activites by creating ISSUEs and +These may include starting Change Requests or in general planning activities by creating ISSUEs and required PRs. All ISSUEs or PRs created to resolve the problem are linked to the Problem Report ISSUE to enable @@ -233,19 +254,19 @@ monitoring of the activities. All activities defined are tracked until closure, means that all linked ISSUEs or PRs are closed or merged, respectively. -If all are closed or merged :need:`Contributor <PROCESS_rl__contributor>` sets Projects status to ``Done`` -to trigger the final review from the :need:`Committer <PROCESS_rl__committer>` to close the Problem -Resolution. +If all are closed or merged :need:`Contributor <PROCESS_rl__contributor>` sets Projects status to +``Done`` to trigger the final review from the :need:`Committer <PROCESS_rl__committer>` to close +the Problem Resolution. The Problem Resolution may also rejected in this phase, then the ISSUE status is set to ``Closed as not planned``. **To 4. Close the Problem Resolution:** -:need:`Committer <PROCESS_rl__committer>` checks finally if the problem is completely resolved. In this -case all linked ISSUEs or PRs are closed or merged, respectively. +:need:`Committer <PROCESS_rl__committer>` checks finally if the problem is completely resolved. In +this case all linked ISSUEs or PRs are closed or merged, respectively. -Especially the solution measure must be checked for their effectivness and the argumentation +Especially the solution measures must be checked for their effectiveness and the argumentation is convincing. :need:`PROCESS_gd_chklst__problem__cr_review` can help to verify whether it can be closed. From 92f3c5ab3f5e802aa5948a6e4e18f8fc27cf78d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Fri, 25 Jul 2025 09:31:44 +0200 Subject: [PATCH 097/102] Delete Tool requirements (#1511) --- docs/requirements/index.rst | 1 - docs/requirements/tool/index.rst | 48 -------------------------------- 2 files changed, 49 deletions(-) delete mode 100644 docs/requirements/tool/index.rst diff --git a/docs/requirements/index.rst b/docs/requirements/index.rst index c5b4b016db..5285c8a475 100644 --- a/docs/requirements/index.rst +++ b/docs/requirements/index.rst @@ -20,4 +20,3 @@ Requirements .. toctree:: stakeholder/index - tool/index \ No newline at end of file diff --git a/docs/requirements/tool/index.rst b/docs/requirements/tool/index.rst deleted file mode 100644 index 9d76df6bb4..0000000000 --- a/docs/requirements/tool/index.rst +++ /dev/null @@ -1,48 +0,0 @@ -.. - # ******************************************************************************* - # Copyright (c) 2024 Contributors to the Eclipse Foundation - # - # See the NOTICE file(s) distributed with this work for additional - # information regarding copyright ownership. - # - # This program and the accompanying materials are made available under the - # terms of the Apache License Version 2.0 which is available at - # https://www.apache.org/licenses/LICENSE-2.0 - # - # SPDX-License-Identifier: Apache-2.0 - # ******************************************************************************* - -.. _tool_requirements: - -Tool Requirements -================= - - -Integration tools ------------------ - - -.. tool_req:: Bazel for unified build, test and integration - :id: tool_req__tool__bazel_build - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__integration__multi_repo - :status: valid - - Bazel shall be used for building, testing and integrating software. - - -Process tools -------------- - - -.. tool_req:: Sphinx-needs for process modelling - :id: tool_req__tool__sphinx_needs_process - :reqtype: Non-Functional - :security: NO - :safety: QM - :satisfies: stkh_req__requirements__as_code - :status: valid - - Spinx-needs shall be used to model all processes within S-CORE. From aed01bde23aa36ef0de73e5ee35bf2e903de94ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Fri, 25 Jul 2025 10:32:39 +0200 Subject: [PATCH 098/102] Increment deps (#1512) Increment dependencies of some modules --- MODULE.bazel | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index d50218fba7..fe5a6d50ad 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -43,7 +43,7 @@ bazel_dep(name = "aspect_rules_py", version = "1.4.0") # Packaging dependencies # ############################################################################### -bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "rules_pkg", version = "1.1.0") ############################################################################### # @@ -51,21 +51,21 @@ bazel_dep(name = "rules_pkg", version = "1.0.1") # Provides formatting and linting of Bazel files. # ############################################################################### -bazel_dep(name = "buildifier_prebuilt", version = "7.3.1") +bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2") ############################################################################### # # Generic linting and formatting rules # ############################################################################### -bazel_dep(name = "aspect_rules_lint", version = "1.4.2") +bazel_dep(name = "aspect_rules_lint", version = "1.4.4") ############################################################################### # # Java version # ############################################################################### -bazel_dep(name = "rules_java", version = "8.11.0") +bazel_dep(name = "rules_java", version = "8.13.0") ############################################################################### # From c8d45dd74beb0d0c9688a3d5f34687b837547575 Mon Sep 17 00:00:00 2001 From: Markus Bechter <markus.bechter@bmw.de> Date: Mon, 28 Jul 2025 14:43:59 +0200 Subject: [PATCH 099/102] docs: Add module architecture diagram --- docs/modules/_assets/module_architecture.drawio.svg | 4 ++++ docs/modules/index.rst | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 docs/modules/_assets/module_architecture.drawio.svg diff --git a/docs/modules/_assets/module_architecture.drawio.svg b/docs/modules/_assets/module_architecture.drawio.svg new file mode 100644 index 0000000000..cb0263989e --- /dev/null +++ b/docs/modules/_assets/module_architecture.drawio.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than draw.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" style="background: transparent; background-color: transparent; color-scheme: light dark;" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="2191px" height="1361px" viewBox="-0.5 -0.5 2191 1361" content="<mxfile host="Electron" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.15 Chrome/134.0.6998.205 Electron/35.2.1 Safari/537.36" version="26.2.15" pages="2"> <diagram name="1.0 Module Architecture" id="kHHpjcKEgZkgKQ2km6BW"> <mxGraphModel dx="3130" dy="1522" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> <root> <mxCell id="X8Ibqyh2nUvShLqAq-5g-0" /> <mxCell id="X8Ibqyh2nUvShLqAq-5g-1" parent="X8Ibqyh2nUvShLqAq-5g-0" /> <object label="baselibs" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-2"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1200" y="850" width="630" height="230" as="geometry" /> </mxCell> </object> <object label="baselibs" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-3"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="20" y="850" width="1160" height="230" as="geometry" /> </mxCell> </object> <object label="logging" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-7"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="740" y="566.25" width="330" height="260" as="geometry" /> </mxCell> </object> <object label="feo" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-9"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="15" y="267.81" width="450" height="267.5" as="geometry" /> </mxCell> </object> <mxCell id="X8Ibqyh2nUvShLqAq-5g-10" value="component" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="50" y="1150" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="X8Ibqyh2nUvShLqAq-5g-11" value="bazel module/&lt;div&gt;repository&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="190" y="1150" width="130" height="60" as="geometry" /> </mxCell> <object label="feo-time" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-12"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="305" y="308.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="feo-com" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-13"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="378.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="feo-log" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-15"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="175" y="378.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="communication" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-21"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="20" y="566.25" width="460" height="250" as="geometry" /> </mxCell> </object> <object label="feo-tracing" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-22"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;dashed=1;dashPattern=8 8;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="305" y="378.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="feo" score-type="component" placeholders="null" id="X8Ibqyh2nUvShLqAq-5g-23"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="308.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="mw::com Frontend" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-24"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fontColor=default;fillColor=#ccd6ff;gradientColor=#FFF2CC;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="627.19" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="Logging API" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-25"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="774" y="616.25" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="feo-cpp" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-27"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#ccd6ff;strokeColor=#d6b656;gradientColor=#FFF2CC;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="175" y="308.44" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="ipc-binding (LoLa)" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-28"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="717.19" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="mw::com Frontend" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-29"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="185" y="627.19" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="Mock binding" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-30"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="185" y="717.19" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="lola- configuration" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-31"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="320" y="717.19" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="memory" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-32"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="40" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="message passing" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-33"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="180" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="json" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-34"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="320" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <mxCell id="X8Ibqyh2nUvShLqAq-5g-35" value="C++&lt;div&gt;component&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="50" y="1220" width="120" height="60" as="geometry" /> </mxCell> <object label="osal" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-36"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="460" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="Logging API" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-37"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#fff2cc;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="909" y="616.25" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="Filesystem" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-38"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="600" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="persistency" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-45"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1090" y="566.25" width="170" height="263.75" as="geometry" /> </mxCell> </object> <object label="kvs" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-46"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#fff2cc;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1110" y="616.25" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="kvs" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-47"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#6c8ebf;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#dae8fc;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1110" y="700" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="filesystem" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-48"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;dashed=1;dashPattern=8 8;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1380" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="json" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-49"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;dashed=1;dashPattern=8 8;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1220" y="890" width="145" height="60" as="geometry" /> </mxCell> </object> <object label="Result" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-50"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="735" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="orchestration" score-type="module" id="X8Ibqyh2nUvShLqAq-5g-55"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1280" y="566.25" width="300" height="263.75" as="geometry" /> </mxCell> </object> <object label="runtime" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-56"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#fff2cc;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1300" y="676.25" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="orchestration" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-57"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#fff2cc;gradientDirection=north;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1300" y="596.25" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="std replacement" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-58"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#fff2cc;gradientDirection=north;dashed=1;dashPattern=8 8;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1515" y="890" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="orchestration cpp" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-59"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#d6b656;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=20;fillColor=#ccd6ff;gradientDirection=south;fontColor=default;gradientColor=#FFF2CC;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1440" y="596.25" width="120" height="60" as="geometry" /> </mxCell> </object> <mxCell id="X8Ibqyh2nUvShLqAq-5g-60" value="Rust&amp;nbsp;&lt;div&gt;component&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="1290" width="125" height="60" as="geometry" /> </mxCell> <object label="futurecpp" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-61"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="40" y="980" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="bitmanipulation" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-62"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="170" y="980" width="140" height="60" as="geometry" /> </mxCell> </object> <object label="concurrency" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-63"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="319" y="980" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="containers" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-64"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="459" y="980" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="safecpp" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-65"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="599" y="980" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="utils" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-66"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="739" y="980" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="static_reflection_&lt;br&gt;with_serialization" score-type="component" id="X8Ibqyh2nUvShLqAq-5g-67"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="990" y="980" width="176" height="60" as="geometry" /> </mxCell> </object> <object label="daal?" score-type="component" id="cyVkqPuj_zZxdIbUwScy-0"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="305" y="448.44" width="120" height="60" as="geometry" /> </mxCell> </object> <mxCell id="cyVkqPuj_zZxdIbUwScy-2" value="" style="endArrow=none;dashed=1;html=1;rounded=0;strokeWidth=3;" parent="X8Ibqyh2nUvShLqAq-5g-1" edge="1"> <mxGeometry width="50" height="50" relative="1" as="geometry"> <mxPoint y="1080.952380952381" as="sourcePoint" /> <mxPoint y="240" as="targetPoint" /> </mxGeometry> </mxCell> <object label="security" score-type="module" id="cyVkqPuj_zZxdIbUwScy-3"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="490" y="271.56" width="460" height="267.5" as="geometry" /> </mxCell> </object> <mxCell id="cyVkqPuj_zZxdIbUwScy-4" value="crypto_libs" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="510" y="311.56" width="190" height="50" as="geometry" /> </mxCell> <mxCell id="cyVkqPuj_zZxdIbUwScy-5" value="crypto_libs" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="520" y="321.56" width="190" height="50" as="geometry" /> </mxCell> <object label="crypto_libs" score-type="component" id="cyVkqPuj_zZxdIbUwScy-6"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="530" y="331.56" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="keystore&lt;div&gt;(HSM abstraction)&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-7"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="520" y="391.56" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="sign_verify" score-type="component" id="cyVkqPuj_zZxdIbUwScy-8"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="520" y="451.56" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="keymgmt" score-type="component" id="cyVkqPuj_zZxdIbUwScy-9"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="740" y="321.56" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="access_mgmt" score-type="component" id="cyVkqPuj_zZxdIbUwScy-10"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="740" y="391.56" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="lifecycle" score-type="module" id="cyVkqPuj_zZxdIbUwScy-12"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="490" y="566.25" width="240" height="253.75" as="geometry" /> </mxCell> </object> <object label="launchmanager" score-type="component" id="cyVkqPuj_zZxdIbUwScy-13"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="510" y="616.25" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="healthmonitor" score-type="component" id="cyVkqPuj_zZxdIbUwScy-14"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="510" y="686.25" width="190" height="50" as="geometry" /> </mxCell> </object> <object label="time" score-type="module" id="cyVkqPuj_zZxdIbUwScy-20"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="980" y="271.56" width="280" height="273.75" as="geometry" /> </mxCell> </object> <object label="gptp_client" score-type="component" id="cyVkqPuj_zZxdIbUwScy-21"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1000" y="311.56" width="110" height="60" as="geometry" /> </mxCell> </object> <object label="time_base_&lt;div&gt;provider&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-22"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1000" y="384.06" width="110" height="60" as="geometry" /> </mxCell> </object> <object label="clock::&lt;br&gt;sync" score-type="component" id="cyVkqPuj_zZxdIbUwScy-23"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1120" y="311.56" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="clock::&lt;br&gt;authentic" score-type="component" id="cyVkqPuj_zZxdIbUwScy-24"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1120" y="384.06" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="time" score-type="component" id="cyVkqPuj_zZxdIbUwScy-26"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1000" y="452.81" width="110" height="60" as="geometry" /> </mxCell> </object> <object label="time" score-type="component" id="cyVkqPuj_zZxdIbUwScy-27"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="870" y="980" width="110" height="60" as="geometry" /> </mxCell> </object> <object label="config" score-type="module" id="cyVkqPuj_zZxdIbUwScy-28"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1280" y="265.31" width="330" height="286.25" as="geometry" /> </mxCell> </object> <object label="config_daemon" score-type="component" id="cyVkqPuj_zZxdIbUwScy-29"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1300" y="307.81" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="config_provider" score-type="component" id="cyVkqPuj_zZxdIbUwScy-30"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1300" y="384.06" width="130" height="60" as="geometry" /> </mxCell> </object> <mxCell id="cyVkqPuj_zZxdIbUwScy-31" value="config_plugins" style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1300" y="452.81" width="130" height="60" as="geometry" /> </mxCell> <mxCell id="cyVkqPuj_zZxdIbUwScy-32" value="config_plugins" style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1310" y="462.81" width="130" height="60" as="geometry" /> </mxCell> <object label="config_plugins" score-type="component" id="cyVkqPuj_zZxdIbUwScy-33"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1320" y="472.81" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="calibration_&lt;div&gt;interface&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-34"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1450" y="307.81" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="faultmanagement" score-type="module" id="cyVkqPuj_zZxdIbUwScy-35"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1610" y="566.25" width="220" height="253.75" as="geometry" /> </mxCell> </object> <object label="opensovd" score-type="external-module" id="cyVkqPuj_zZxdIbUwScy-37"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-360" y="266.25" width="340" height="423.12" as="geometry" /> </mxCell> </object> <object label="fauit_library" score-type="component" score-language="-" id="cyVkqPuj_zZxdIbUwScy-38"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="303.12" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="diagnostic_&lt;div&gt;fault_manager&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-39"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="371.56000000000006" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="diagnostic_&lt;div&gt;database&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-40"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="443.12" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="sovd_server" score-type="component" id="cyVkqPuj_zZxdIbUwScy-41"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-195" y="303.12" width="165" height="60" as="geometry" /> </mxCell> </object> <object label="sovd_gateway" score-type="component" id="cyVkqPuj_zZxdIbUwScy-42"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-195" y="371.56" width="165" height="60" as="geometry" /> </mxCell> </object> <object label="classic_diagnostic&lt;div&gt;_adapter&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-43"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-195" y="443.12" width="165" height="60" as="geometry" /> </mxCell> </object> <object label="sovd_client" score-type="component" id="cyVkqPuj_zZxdIbUwScy-44"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="589.37" width="130" height="60" as="geometry" /> </mxCell> </object> <mxCell id="cyVkqPuj_zZxdIbUwScy-45" value="uds2sovd_&lt;div&gt;proxy&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="515.62" width="130" height="60" as="geometry" /> </mxCell> <object label="diagnostic_&lt;div&gt;service_app&lt;/div&gt;" score-type="component" id="cyVkqPuj_zZxdIbUwScy-46"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-195" y="515.62" width="165" height="60" as="geometry" /> </mxCell> </object> <object label="someip" score-type="external-module" id="cyVkqPuj_zZxdIbUwScy-48"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-360" y="730" width="340" height="250" as="geometry" /> </mxCell> </object> <object label="score_someip_&lt;div&gt;gateway&lt;/div&gt;" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-4"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="780" width="150" height="60" as="geometry" /> </mxCell> </object> <object label="someip_&lt;div&gt;protocol&lt;/div&gt;" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-5"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="-340" y="851.56" width="150" height="60" as="geometry" /> </mxCell> </object> <object label="abi-compatible-datatypes" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-7"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="870" y="890" width="160" height="60" as="geometry" /> </mxCell> </object> <object label="abi-compatible-datatypes" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-8"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1220" y="970" width="145" height="60" as="geometry" /> </mxCell> </object> <object label="ai-platform" score-type="module" id="zOfhbxZQrp5VTqdj2Vb1-9"> <mxCell style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1630" y="269.69" width="200" height="275.62" as="geometry" /> </mxCell> </object> <object label="inference_&lt;div&gt;adapter&lt;/div&gt;" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-10"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1660" y="311.56" width="130" height="60" as="geometry" /> </mxCell> </object> <object label="onnx_runtime" score-type="component" id="zOfhbxZQrp5VTqdj2Vb1-15"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=19;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="1660" y="384.06" width="130" height="60" as="geometry" /> </mxCell> </object> <mxCell id="zOfhbxZQrp5VTqdj2Vb1-17" value="ext module/&lt;div&gt;repository&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;fontSize=20;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="190" y="1230" width="130" height="60" as="geometry" /> </mxCell> <object label="datarouter" score-type="component" id="lLnuWv548SjsVmpskmR--0"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="774" y="700" width="120" height="60" as="geometry" /> </mxCell> </object> <object label="record/&lt;div&gt;replay&lt;/div&gt;" score-type="component" id="lLnuWv548SjsVmpskmR--4"> <mxCell style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="175" y="448.44" width="120" height="60" as="geometry" /> </mxCell> </object> <mxCell id="H0D6Iy5TQXu2IpcHdf1l-1" value="language to be defined" style="rounded=0;whiteSpace=wrap;html=1;fontSize=20;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="45" y="1360" width="125" height="60" as="geometry" /> </mxCell> <mxCell id="H0D6Iy5TQXu2IpcHdf1l-3" value="Modules and Components of S-CORE 1.0" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=60;" parent="X8Ibqyh2nUvShLqAq-5g-1" vertex="1"> <mxGeometry x="20" y="60" width="1220" height="100" as="geometry" /> </mxCell> </root> </mxGraphModel> </diagram> <diagram id="E6MF477lCpV7keu6hLqp" name="Fallback QNX 8"> <mxGraphModel dx="2335" dy="823" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> <root> <mxCell id="0" /> <mxCell id="1" parent="0" /> <mxCell id="1k3IXSwx12tV7RTQSR1Z-2" value="Baselibs" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1"> <mxGeometry x="40" y="850" width="850" height="230" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-6" target="1k3IXSwx12tV7RTQSR1Z-35" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="805" y="810" /> <mxPoint x="540" y="810" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.406;exitY=0.994;exitDx=0;exitDy=0;exitPerimeter=0;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-6" target="1k3IXSwx12tV7RTQSR1Z-33" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="805" y="768" /> <mxPoint x="805" y="810" /> <mxPoint x="400" y="810" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-6" target="1k3IXSwx12tV7RTQSR1Z-37" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="805" y="810" /> <mxPoint x="680" y="810" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-6" value="Logging" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1"> <mxGeometry x="640" y="510" width="330" height="260" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-9" value="Component" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1"> <mxGeometry x="730" y="50" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-10" value="Module" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1"> <mxGeometry x="910" y="30" width="130" height="70" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-20" target="1k3IXSwx12tV7RTQSR1Z-24" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-20" target="1k3IXSwx12tV7RTQSR1Z-33" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="260" y="840" /> <mxPoint x="400" y="840" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-20" target="1k3IXSwx12tV7RTQSR1Z-34" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="-120" y="700" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-20" target="1k3IXSwx12tV7RTQSR1Z-32" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-20" target="1k3IXSwx12tV7RTQSR1Z-31" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="260" y="840" /> <mxPoint x="120" y="840" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-20" value="Communication" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1"> <mxGeometry x="30" y="510" width="460" height="250" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-24" value="Logging API" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="674" y="560" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-27" value="IPC binding (LoLa)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="70" y="660" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-28" value="mw::com Frontend" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="210" y="570" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-29" value="Mock binding" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="210" y="660" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-30" value="LoLa Configuration" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="350" y="660" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-31" value="memory" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="60" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-32" value="Message Passing" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="200" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-33" value="JSON&amp;nbsp;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="340" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-34" value="&amp;nbsp;tracing (frontend)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;dashed=1;dashPattern=8 8;" parent="1" vertex="1"> <mxGeometry x="-200" y="680" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-35" value="&quot;OSAL&quot;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="480" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-37" value="Filesystem" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="620" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-44" target="1k3IXSwx12tV7RTQSR1Z-37" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="1170" y="820" /> <mxPoint x="680" y="820" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-44" target="1k3IXSwx12tV7RTQSR1Z-33" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="1170" y="820" /> <mxPoint x="400" y="820" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-44" target="1k3IXSwx12tV7RTQSR1Z-6" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;jumpStyle=arc;" parent="1" source="1k3IXSwx12tV7RTQSR1Z-44" target="1k3IXSwx12tV7RTQSR1Z-49" edge="1"> <mxGeometry relative="1" as="geometry"> <Array as="points"> <mxPoint x="1170" y="820" /> <mxPoint x="830" y="820" /> </Array> </mxGeometry> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-44" value="Persistency" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1"> <mxGeometry x="1020" y="510" width="300" height="140" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-46" value="kvs" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#6c8ebf;align=center;verticalAlign=middle;fontFamily=Helvetica;fontSize=12;fillColor=#dae8fc;gradientDirection=north;" parent="1" vertex="1"> <mxGeometry x="1170" y="560" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-49" value="Result" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="760" y="890" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-60" value="futurecpp" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="60" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-61" value="bitmanipulation" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="190" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-62" value="concurrency" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="330" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-63" value="containers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="460" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-64" value="safecpp" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="590" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-65" value="utils" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="720" y="980" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-66" value="static_reflection_&lt;br&gt;with_serialization" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="674" y="650" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-67" value="Third-party?" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;dashed=1;dashPattern=8 8;" parent="1" vertex="1"> <mxGeometry x="544" y="1280" width="650" height="150" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-68" value="nlohman json" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1"> <mxGeometry x="570" y="1310" width="120" height="60" as="geometry" /> </mxCell> <mxCell id="1k3IXSwx12tV7RTQSR1Z-69" value="tiny-json" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1"> <mxGeometry x="700" y="1310" width="120" height="60" as="geometry" /> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> "><defs><linearGradient x1="0%" y1="100%" x2="0%" y2="0%" id="drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_fff2cc-1-_ccd6ff-1-s-0"><stop offset="0%" stop-color="#ccd6ff" stop-opacity="1" style="stop-color: rgb(204, 214, 255); stop-opacity: 1;"/><stop offset="100%" stop-color="#FFF2CC" stop-opacity="1" style="stop-color: rgb(255, 242, 204); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_ccd6ff-1-_fff2cc-1-s-0"><stop offset="0%" stop-color="#ccd6ff" stop-opacity="1" style="stop-color: rgb(204, 214, 255); stop-opacity: 1;"/><stop offset="100%" stop-color="#FFF2CC" stop-opacity="1" style="stop-color: rgb(255, 242, 204); stop-opacity: 1;"/></linearGradient></defs><g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-0"><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-1"><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-2"><g id="cell-X8Ibqyh2nUvShLqAq-5g-2" content="<object label="baselibs" score-type="module"/>" data-label="baselibs" data-score-type="module"><g><rect x="1560" y="790" width="630" height="230" rx="34.5" ry="34.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 628px; height: 1px; padding-top: 797px; margin-left: 1561px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">baselibs</div></div></div></foreignObject><text x="1875" y="817" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">baselibs</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-3"><g id="cell-X8Ibqyh2nUvShLqAq-5g-3" content="<object label="baselibs" score-type="module"/>" data-label="baselibs" data-score-type="module"><g><rect x="380" y="790" width="1160" height="230" rx="34.5" ry="34.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1158px; height: 1px; padding-top: 797px; margin-left: 381px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">baselibs</div></div></div></foreignObject><text x="960" y="817" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">baselibs</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-7"><g id="cell-X8Ibqyh2nUvShLqAq-5g-7" content="<object label="logging" score-type="module"/>" data-label="logging" data-score-type="module"><g><rect x="1100" y="506.25" width="330" height="260" rx="39" ry="39" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 328px; height: 1px; padding-top: 513px; margin-left: 1101px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">logging</div></div></div></foreignObject><text x="1265" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">logging</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-9"><g id="cell-X8Ibqyh2nUvShLqAq-5g-9" content="<object label="feo" score-type="module"/>" data-label="feo" data-score-type="module"><g><rect x="375" y="207.81" width="450" height="267.5" rx="40.13" ry="40.13" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 448px; height: 1px; padding-top: 215px; margin-left: 376px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo</div></div></div></foreignObject><text x="600" y="235" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-10"><g id="cell-X8Ibqyh2nUvShLqAq-5g-10"><g><rect x="410" y="1090" width="120" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 1120px; margin-left: 411px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">component</div></div></div></foreignObject><text x="470" y="1126" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">component</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-11"><g id="cell-X8Ibqyh2nUvShLqAq-5g-11"><g><rect x="550" y="1090" width="130" height="60" rx="9" ry="9" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 1097px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">bazel module/<div>repository</div></div></div></div></foreignObject><text x="615" y="1117" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">bazel module/...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-12"><g id="cell-X8Ibqyh2nUvShLqAq-5g-12" content="<object label="feo-time" score-type="component"/>" data-label="feo-time" data-score-type="component"><g><rect x="665" y="248.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 278px; margin-left: 666px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo-time</div></div></div></foreignObject><text x="725" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo-time</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-13"><g id="cell-X8Ibqyh2nUvShLqAq-5g-13" content="<object label="feo-com" score-type="component"/>" data-label="feo-com" data-score-type="component"><g><rect x="405" y="318.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 348px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo-com</div></div></div></foreignObject><text x="465" y="354" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo-com</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-15"><g id="cell-X8Ibqyh2nUvShLqAq-5g-15" content="<object label="feo-log" score-type="component"/>" data-label="feo-log" data-score-type="component"><g><rect x="535" y="318.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 348px; margin-left: 536px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo-log</div></div></div></foreignObject><text x="595" y="354" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo-log</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-21"><g id="cell-X8Ibqyh2nUvShLqAq-5g-21" content="<object label="communication" score-type="module"/>" data-label="communication" data-score-type="module"><g><rect x="380" y="506.25" width="460" height="250" rx="37.5" ry="37.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 458px; height: 1px; padding-top: 513px; margin-left: 381px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">communication</div></div></div></foreignObject><text x="610" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">communication</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-22"><g id="cell-X8Ibqyh2nUvShLqAq-5g-22" content="<object label="feo-tracing" score-type="component"/>" data-label="feo-tracing" data-score-type="component"><g><rect x="665" y="318.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="8 8" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 348px; margin-left: 666px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo-tracing</div></div></div></foreignObject><text x="725" y="354" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo-tracing</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-23"><g id="cell-X8Ibqyh2nUvShLqAq-5g-23" content="<object label="feo" score-type="component" placeholders="null"/>" data-label="feo" data-score-type="component" data-placeholders="null"><g><rect x="405" y="248.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 278px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo</div></div></div></foreignObject><text x="465" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-24"><g id="cell-X8Ibqyh2nUvShLqAq-5g-24" content="<object label="mw::com Frontend" score-type="component"/>" data-label="mw::com Frontend" data-score-type="component"><g><rect x="405" y="567.19" width="120" height="60" fill="url(#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_fff2cc-1-_ccd6ff-1-s-0)" stroke="#d6b656" pointer-events="all" style="fill: url("#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_fff2cc-1-_ccd6ff-1-s-0"); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 597px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">mw::com Frontend</div></div></div></foreignObject><text x="465" y="603" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">mw::com Fron...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-25"><g id="cell-X8Ibqyh2nUvShLqAq-5g-25" content="<object label="Logging API" score-type="component"/>" data-label="Logging API" data-score-type="component"><g><rect x="1134" y="556.25" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 586px; margin-left: 1135px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Logging API</div></div></div></foreignObject><text x="1194" y="592" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Logging API</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-27"><g id="cell-X8Ibqyh2nUvShLqAq-5g-27" content="<object label="feo-cpp" score-type="component"/>" data-label="feo-cpp" data-score-type="component"><g><rect x="535" y="248.44" width="120" height="60" fill="url(#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_ccd6ff-1-_fff2cc-1-s-0)" stroke="#d6b656" pointer-events="all" style="fill: url("#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_ccd6ff-1-_fff2cc-1-s-0"); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 278px; margin-left: 536px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">feo-cpp</div></div></div></foreignObject><text x="595" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">feo-cpp</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-28"><g id="cell-X8Ibqyh2nUvShLqAq-5g-28" content="<object label="ipc-binding (LoLa)" score-type="component"/>" data-label="ipc-binding (LoLa)" data-score-type="component"><g><rect x="405" y="657.19" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 687px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">ipc-binding (LoLa)</div></div></div></foreignObject><text x="465" y="693" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">ipc-binding...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-29"><g id="cell-X8Ibqyh2nUvShLqAq-5g-29" content="<object label="mw::com Frontend" score-type="component"/>" data-label="mw::com Frontend" data-score-type="component"><g><rect x="545" y="567.19" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 597px; margin-left: 546px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">mw::com Frontend</div></div></div></foreignObject><text x="605" y="603" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">mw::com Fron...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-30"><g id="cell-X8Ibqyh2nUvShLqAq-5g-30" content="<object label="Mock binding" score-type="component"/>" data-label="Mock binding" data-score-type="component"><g><rect x="545" y="657.19" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 687px; margin-left: 546px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Mock binding</div></div></div></foreignObject><text x="605" y="693" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Mock binding</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-31"><g id="cell-X8Ibqyh2nUvShLqAq-5g-31" content="<object label="lola- configuration" score-type="component"/>" data-label="lola- configuration" data-score-type="component"><g><rect x="680" y="657.19" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 687px; margin-left: 681px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">lola- configuration</div></div></div></foreignObject><text x="740" y="693" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">lola- config...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-32"><g id="cell-X8Ibqyh2nUvShLqAq-5g-32" content="<object label="memory" score-type="component"/>" data-label="memory" data-score-type="component"><g><rect x="400" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 401px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">memory</div></div></div></foreignObject><text x="460" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">memory</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-33"><g id="cell-X8Ibqyh2nUvShLqAq-5g-33" content="<object label="message passing" score-type="component"/>" data-label="message passing" data-score-type="component"><g><rect x="540" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 541px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">message passing</div></div></div></foreignObject><text x="600" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">message pass...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-34"><g id="cell-X8Ibqyh2nUvShLqAq-5g-34" content="<object label="json" score-type="component"/>" data-label="json" data-score-type="component"><g><rect x="680" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 681px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">json</div></div></div></foreignObject><text x="740" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">json</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-35"><g id="cell-X8Ibqyh2nUvShLqAq-5g-35"><g><rect x="410" y="1160" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 1190px; margin-left: 411px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">C++<div>component</div></div></div></div></foreignObject><text x="470" y="1196" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">C++...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-36"><g id="cell-X8Ibqyh2nUvShLqAq-5g-36" content="<object label="osal" score-type="component"/>" data-label="osal" data-score-type="component"><g><rect x="820" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 821px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">osal</div></div></div></foreignObject><text x="880" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">osal</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-37"><g id="cell-X8Ibqyh2nUvShLqAq-5g-37" content="<object label="Logging API" score-type="component"/>" data-label="Logging API" data-score-type="component"><g><rect x="1269" y="556.25" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 586px; margin-left: 1270px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Logging API</div></div></div></foreignObject><text x="1329" y="592" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Logging API</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-38"><g id="cell-X8Ibqyh2nUvShLqAq-5g-38" content="<object label="Filesystem" score-type="component"/>" data-label="Filesystem" data-score-type="component"><g><rect x="960" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 961px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Filesystem</div></div></div></foreignObject><text x="1020" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Filesystem</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-45"><g id="cell-X8Ibqyh2nUvShLqAq-5g-45" content="<object label="persistency" score-type="module"/>" data-label="persistency" data-score-type="module"><g><rect x="1450" y="506.25" width="170" height="263.75" rx="25.5" ry="25.5" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 168px; height: 1px; padding-top: 513px; margin-left: 1451px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">persistency</div></div></div></foreignObject><text x="1535" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">persistency</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-46"><g id="cell-X8Ibqyh2nUvShLqAq-5g-46" content="<object label="kvs" score-type="component"/>" data-label="kvs" data-score-type="component"><g><rect x="1470" y="556.25" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 586px; margin-left: 1471px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">kvs</div></div></div></foreignObject><text x="1530" y="592" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">kvs</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-47"><g id="cell-X8Ibqyh2nUvShLqAq-5g-47" content="<object label="kvs" score-type="component"/>" data-label="kvs" data-score-type="component"><g><rect x="1470" y="640" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 670px; margin-left: 1471px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">kvs</div></div></div></foreignObject><text x="1530" y="676" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">kvs</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-48"><g id="cell-X8Ibqyh2nUvShLqAq-5g-48" content="<object label="filesystem" score-type="component"/>" data-label="filesystem" data-score-type="component"><g><rect x="1740" y="830" width="120" height="60" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="8 8" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 1741px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">filesystem</div></div></div></foreignObject><text x="1800" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">filesystem</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-49"><g id="cell-X8Ibqyh2nUvShLqAq-5g-49" content="<object label="json" score-type="component"/>" data-label="json" data-score-type="component"><g><rect x="1580" y="830" width="145" height="60" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="8 8" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 143px; height: 1px; padding-top: 860px; margin-left: 1581px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">json</div></div></div></foreignObject><text x="1653" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">json</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-50"><g id="cell-X8Ibqyh2nUvShLqAq-5g-50" content="<object label="Result" score-type="component"/>" data-label="Result" data-score-type="component"><g><rect x="1095" y="830" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 1096px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Result</div></div></div></foreignObject><text x="1155" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Result</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-55"><g id="cell-X8Ibqyh2nUvShLqAq-5g-55" content="<object label="orchestration" score-type="module"/>" data-label="orchestration" data-score-type="module"><g><rect x="1640" y="506.25" width="300" height="263.75" rx="39.56" ry="39.56" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 298px; height: 1px; padding-top: 513px; margin-left: 1641px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">orchestration</div></div></div></foreignObject><text x="1790" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">orchestration</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-56"><g id="cell-X8Ibqyh2nUvShLqAq-5g-56" content="<object label="runtime" score-type="component"/>" data-label="runtime" data-score-type="component"><g><rect x="1660" y="616.25" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 646px; margin-left: 1661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">runtime</div></div></div></foreignObject><text x="1720" y="652" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">runtime</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-57"><g id="cell-X8Ibqyh2nUvShLqAq-5g-57" content="<object label="orchestration" score-type="component"/>" data-label="orchestration" data-score-type="component"><g><rect x="1660" y="536.25" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 566px; margin-left: 1661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">orchestration</div></div></div></foreignObject><text x="1720" y="572" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">orchestration</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-58"><g id="cell-X8Ibqyh2nUvShLqAq-5g-58" content="<object label="std replacement" score-type="component"/>" data-label="std replacement" data-score-type="component"><g><rect x="1875" y="830" width="120" height="60" fill="#fff2cc" stroke="#d6b656" stroke-dasharray="8 8" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 860px; margin-left: 1876px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">std replacement</div></div></div></foreignObject><text x="1935" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">std replacem...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-59"><g id="cell-X8Ibqyh2nUvShLqAq-5g-59" content="<object label="orchestration cpp" score-type="component"/>" data-label="orchestration cpp" data-score-type="component"><g><rect x="1800" y="536.25" width="120" height="60" fill="url(#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_ccd6ff-1-_fff2cc-1-s-0)" stroke="#d6b656" pointer-events="all" style="fill: url("#drawio-svg-dOODWABOc8lKBWiuNx1C-gradient-_ccd6ff-1-_fff2cc-1-s-0"); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 566px; margin-left: 1801px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">orchestration cpp</div></div></div></foreignObject><text x="1860" y="572" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">orchestratio...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-60"><g id="cell-X8Ibqyh2nUvShLqAq-5g-60"><g><rect x="405" y="1230" width="125" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 123px; height: 1px; padding-top: 1260px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Rust <div>component</div></div></div></div></foreignObject><text x="468" y="1266" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">Rust...</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-61"><g id="cell-X8Ibqyh2nUvShLqAq-5g-61" content="<object label="futurecpp" score-type="component"/>" data-label="futurecpp" data-score-type="component"><g><rect x="400" y="920" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 950px; margin-left: 401px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">futurecpp</div></div></div></foreignObject><text x="460" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">futurecpp</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-62"><g id="cell-X8Ibqyh2nUvShLqAq-5g-62" content="<object label="bitmanipulation" score-type="component"/>" data-label="bitmanipulation" data-score-type="component"><g><rect x="530" y="920" width="140" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 138px; height: 1px; padding-top: 950px; margin-left: 531px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">bitmanipulation</div></div></div></foreignObject><text x="600" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">bitmanipulation</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-63"><g id="cell-X8Ibqyh2nUvShLqAq-5g-63" content="<object label="concurrency" score-type="component"/>" data-label="concurrency" data-score-type="component"><g><rect x="679" y="920" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 950px; margin-left: 680px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">concurrency</div></div></div></foreignObject><text x="739" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">concurrency</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-64"><g id="cell-X8Ibqyh2nUvShLqAq-5g-64" content="<object label="containers" score-type="component"/>" data-label="containers" data-score-type="component"><g><rect x="819" y="920" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 950px; margin-left: 820px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">containers</div></div></div></foreignObject><text x="879" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">containers</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-65"><g id="cell-X8Ibqyh2nUvShLqAq-5g-65" content="<object label="safecpp" score-type="component"/>" data-label="safecpp" data-score-type="component"><g><rect x="959" y="920" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 950px; margin-left: 960px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">safecpp</div></div></div></foreignObject><text x="1019" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">safecpp</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-66"><g id="cell-X8Ibqyh2nUvShLqAq-5g-66" content="<object label="utils" score-type="component"/>" data-label="utils" data-score-type="component"><g><rect x="1099" y="920" width="120" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 950px; margin-left: 1100px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">utils</div></div></div></foreignObject><text x="1159" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">utils</text></switch></g></g></g></g><g data-cell-id="X8Ibqyh2nUvShLqAq-5g-67"><g id="cell-X8Ibqyh2nUvShLqAq-5g-67" content="<object label="static_reflection_&lt;br&gt;with_serialization" score-type="component"/>" data-label="static_reflection_<br>with_serialization" data-score-type="component"><g><rect x="1350" y="920" width="176" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 174px; height: 1px; padding-top: 950px; margin-left: 1351px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">static_reflection_<br />with_serialization</div></div></div></foreignObject><text x="1438" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">static_reflection_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-0"><g id="cell-cyVkqPuj_zZxdIbUwScy-0" content="<object label="daal?" score-type="component"/>" data-label="daal?" data-score-type="component"><g><rect x="665" y="388.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 418px; margin-left: 666px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">daal?</div></div></div></foreignObject><text x="725" y="424" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">daal?</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-2"><g id="cell-cyVkqPuj_zZxdIbUwScy-2"><g><path d="M 360 1020.95 L 360 180" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" stroke-dasharray="9 9" pointer-events="stroke" style="stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-3"><g id="cell-cyVkqPuj_zZxdIbUwScy-3" content="<object label="security" score-type="module"/>" data-label="security" data-score-type="module"><g><rect x="850" y="211.56" width="460" height="267.5" rx="40.13" ry="40.13" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 458px; height: 1px; padding-top: 219px; margin-left: 851px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">security</div></div></div></foreignObject><text x="1080" y="239" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">security</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-4"><g id="cell-cyVkqPuj_zZxdIbUwScy-4"><g><rect x="870" y="251.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 277px; margin-left: 871px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">crypto_libs</div></div></div></foreignObject><text x="965" y="283" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">crypto_libs</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-5"><g id="cell-cyVkqPuj_zZxdIbUwScy-5"><g><rect x="880" y="261.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 287px; margin-left: 881px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">crypto_libs</div></div></div></foreignObject><text x="975" y="293" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">crypto_libs</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-6"><g id="cell-cyVkqPuj_zZxdIbUwScy-6" content="<object label="crypto_libs" score-type="component"/>" data-label="crypto_libs" data-score-type="component"><g><rect x="890" y="271.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 297px; margin-left: 891px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">crypto_libs</div></div></div></foreignObject><text x="985" y="303" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">crypto_libs</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-7"><g id="cell-cyVkqPuj_zZxdIbUwScy-7" content="<object label="keystore&lt;div&gt;(HSM abstraction)&lt;/div&gt;" score-type="component"/>" data-label="keystore<div>(HSM abstraction)</div>" data-score-type="component"><g><rect x="880" y="331.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 357px; margin-left: 881px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">keystore<div>(HSM abstraction)</div></div></div></div></foreignObject><text x="975" y="363" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">keystore...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-8"><g id="cell-cyVkqPuj_zZxdIbUwScy-8" content="<object label="sign_verify" score-type="component"/>" data-label="sign_verify" data-score-type="component"><g><rect x="880" y="391.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 417px; margin-left: 881px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">sign_verify</div></div></div></foreignObject><text x="975" y="423" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">sign_verify</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-9"><g id="cell-cyVkqPuj_zZxdIbUwScy-9" content="<object label="keymgmt" score-type="component"/>" data-label="keymgmt" data-score-type="component"><g><rect x="1100" y="261.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 287px; margin-left: 1101px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">keymgmt</div></div></div></foreignObject><text x="1195" y="293" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">keymgmt</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-10"><g id="cell-cyVkqPuj_zZxdIbUwScy-10" content="<object label="access_mgmt" score-type="component"/>" data-label="access_mgmt" data-score-type="component"><g><rect x="1100" y="331.56" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 357px; margin-left: 1101px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">access_mgmt</div></div></div></foreignObject><text x="1195" y="363" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">access_mgmt</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-12"><g id="cell-cyVkqPuj_zZxdIbUwScy-12" content="<object label="lifecycle" score-type="module"/>" data-label="lifecycle" data-score-type="module"><g><rect x="850" y="506.25" width="240" height="253.75" rx="36" ry="36" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 238px; height: 1px; padding-top: 513px; margin-left: 851px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">lifecycle</div></div></div></foreignObject><text x="970" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">lifecycle</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-13"><g id="cell-cyVkqPuj_zZxdIbUwScy-13" content="<object label="launchmanager" score-type="component"/>" data-label="launchmanager" data-score-type="component"><g><rect x="870" y="556.25" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 581px; margin-left: 871px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">launchmanager</div></div></div></foreignObject><text x="965" y="587" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">launchmanager</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-14"><g id="cell-cyVkqPuj_zZxdIbUwScy-14" content="<object label="healthmonitor" score-type="component"/>" data-label="healthmonitor" data-score-type="component"><g><rect x="870" y="626.25" width="190" height="50" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 651px; margin-left: 871px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">healthmonitor</div></div></div></foreignObject><text x="965" y="657" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">healthmonitor</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-20"><g id="cell-cyVkqPuj_zZxdIbUwScy-20" content="<object label="time" score-type="module"/>" data-label="time" data-score-type="module"><g><rect x="1340" y="211.56" width="280" height="273.75" rx="41.06" ry="41.06" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 278px; height: 1px; padding-top: 219px; margin-left: 1341px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">time</div></div></div></foreignObject><text x="1480" y="239" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">time</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-21"><g id="cell-cyVkqPuj_zZxdIbUwScy-21" content="<object label="gptp_client" score-type="component"/>" data-label="gptp_client" data-score-type="component"><g><rect x="1360" y="251.56" width="110" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 282px; margin-left: 1361px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">gptp_client</div></div></div></foreignObject><text x="1415" y="287" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">gptp_client</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-22"><g id="cell-cyVkqPuj_zZxdIbUwScy-22" content="<object label="time_base_&lt;div&gt;provider&lt;/div&gt;" score-type="component"/>" data-label="time_base_<div>provider</div>" data-score-type="component"><g><rect x="1360" y="324.06" width="110" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 354px; margin-left: 1361px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">time_base_<div>provider</div></div></div></div></foreignObject><text x="1415" y="360" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">time_base_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-23"><g id="cell-cyVkqPuj_zZxdIbUwScy-23" content="<object label="clock::&lt;br&gt;sync" score-type="component"/>" data-label="clock::<br>sync" data-score-type="component"><g><rect x="1480" y="251.56" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 282px; margin-left: 1481px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">clock::<br />sync</div></div></div></foreignObject><text x="1545" y="287" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">clock::...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-24"><g id="cell-cyVkqPuj_zZxdIbUwScy-24" content="<object label="clock::&lt;br&gt;authentic" score-type="component"/>" data-label="clock::<br>authentic" data-score-type="component"><g><rect x="1480" y="324.06" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 354px; margin-left: 1481px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">clock::<br />authentic</div></div></div></foreignObject><text x="1545" y="360" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">clock::...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-26"><g id="cell-cyVkqPuj_zZxdIbUwScy-26" content="<object label="time" score-type="component"/>" data-label="time" data-score-type="component"><g><rect x="1360" y="392.81" width="110" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 423px; margin-left: 1361px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">time</div></div></div></foreignObject><text x="1415" y="429" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">time</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-27"><g id="cell-cyVkqPuj_zZxdIbUwScy-27" content="<object label="time" score-type="component"/>" data-label="time" data-score-type="component"><g><rect x="1230" y="920" width="110" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 950px; margin-left: 1231px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">time</div></div></div></foreignObject><text x="1285" y="956" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">time</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-28"><g id="cell-cyVkqPuj_zZxdIbUwScy-28" content="<object label="config" score-type="module"/>" data-label="config" data-score-type="module"><g><rect x="1640" y="205.31" width="330" height="286.25" rx="42.94" ry="42.94" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 328px; height: 1px; padding-top: 212px; margin-left: 1641px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config</div></div></div></foreignObject><text x="1805" y="232" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">config</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-29"><g id="cell-cyVkqPuj_zZxdIbUwScy-29" content="<object label="config_daemon" score-type="component"/>" data-label="config_daemon" data-score-type="component"><g><rect x="1660" y="247.81" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 278px; margin-left: 1661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config_daemon</div></div></div></foreignObject><text x="1725" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">config_daemon</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-30"><g id="cell-cyVkqPuj_zZxdIbUwScy-30" content="<object label="config_provider" score-type="component"/>" data-label="config_provider" data-score-type="component"><g><rect x="1660" y="324.06" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 354px; margin-left: 1661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config_provider</div></div></div></foreignObject><text x="1725" y="360" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">config_provider</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-31"><g id="cell-cyVkqPuj_zZxdIbUwScy-31"><g><rect x="1660" y="392.81" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 423px; margin-left: 1661px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config_plugins</div></div></div></foreignObject><text x="1725" y="429" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">config_plugins</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-32"><g id="cell-cyVkqPuj_zZxdIbUwScy-32"><g><rect x="1670" y="402.81" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 433px; margin-left: 1671px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config_plugins</div></div></div></foreignObject><text x="1735" y="439" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">config_plugins</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-33"><g id="cell-cyVkqPuj_zZxdIbUwScy-33" content="<object label="config_plugins" score-type="component"/>" data-label="config_plugins" data-score-type="component"><g><rect x="1680" y="412.81" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 443px; margin-left: 1681px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">config_plugins</div></div></div></foreignObject><text x="1745" y="449" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">config_plugins</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-34"><g id="cell-cyVkqPuj_zZxdIbUwScy-34" content="<object label="calibration_&lt;div&gt;interface&lt;/div&gt;" score-type="component"/>" data-label="calibration_<div>interface</div>" data-score-type="component"><g><rect x="1810" y="247.81" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 278px; margin-left: 1811px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">calibration_<div>interface</div></div></div></div></foreignObject><text x="1875" y="284" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">calibration_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-35"><g id="cell-cyVkqPuj_zZxdIbUwScy-35" content="<object label="faultmanagement" score-type="module"/>" data-label="faultmanagement" data-score-type="module"><g><rect x="1970" y="506.25" width="220" height="253.75" rx="33" ry="33" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 513px; margin-left: 1971px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">faultmanagement</div></div></div></foreignObject><text x="2080" y="533" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">faultmanagement</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-37"><g id="cell-cyVkqPuj_zZxdIbUwScy-37" content="<object label="opensovd" score-type="external-module"/>" data-label="opensovd" data-score-type="external-module"><g><rect x="0" y="206.25" width="340" height="423.12" rx="51" ry="51" fill="#f5f5f5" stroke="#666666" pointer-events="all" style="fill: rgb(245, 245, 245); stroke: rgb(102, 102, 102);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 338px; height: 1px; padding-top: 213px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">opensovd</div></div></div></foreignObject><text x="170" y="233" fill="#333333" font-family=""Helvetica"" font-size="20px" text-anchor="middle">opensovd</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-38"><g id="cell-cyVkqPuj_zZxdIbUwScy-38" content="<object label="fauit_library" score-type="component" score-language="-"/>" data-label="fauit_library" data-score-type="component" data-score-language="-"><g><rect x="20" y="243.12" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 273px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">fauit_library</div></div></div></foreignObject><text x="85" y="279" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">fauit_library</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-39"><g id="cell-cyVkqPuj_zZxdIbUwScy-39" content="<object label="diagnostic_&lt;div&gt;fault_manager&lt;/div&gt;" score-type="component"/>" data-label="diagnostic_<div>fault_manager</div>" data-score-type="component"><g><rect x="20" y="311.56" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 342px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">diagnostic_<div>fault_manager</div></div></div></div></foreignObject><text x="85" y="347" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">diagnostic_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-40"><g id="cell-cyVkqPuj_zZxdIbUwScy-40" content="<object label="diagnostic_&lt;div&gt;database&lt;/div&gt;" score-type="component"/>" data-label="diagnostic_<div>database</div>" data-score-type="component"><g><rect x="20" y="383.12" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 413px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">diagnostic_<div>database</div></div></div></div></foreignObject><text x="85" y="419" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">diagnostic_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-41"><g id="cell-cyVkqPuj_zZxdIbUwScy-41" content="<object label="sovd_server" score-type="component"/>" data-label="sovd_server" data-score-type="component"><g><rect x="165" y="243.12" width="165" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 163px; height: 1px; padding-top: 273px; margin-left: 166px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">sovd_server</div></div></div></foreignObject><text x="248" y="279" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">sovd_server</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-42"><g id="cell-cyVkqPuj_zZxdIbUwScy-42" content="<object label="sovd_gateway" score-type="component"/>" data-label="sovd_gateway" data-score-type="component"><g><rect x="165" y="311.56" width="165" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 163px; height: 1px; padding-top: 342px; margin-left: 166px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">sovd_gateway</div></div></div></foreignObject><text x="248" y="347" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">sovd_gateway</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-43"><g id="cell-cyVkqPuj_zZxdIbUwScy-43" content="<object label="classic_diagnostic&lt;div&gt;_adapter&lt;/div&gt;" score-type="component"/>" data-label="classic_diagnostic<div>_adapter</div>" data-score-type="component"><g><rect x="165" y="383.12" width="165" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 163px; height: 1px; padding-top: 413px; margin-left: 166px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">classic_diagnostic<div>_adapter</div></div></div></div></foreignObject><text x="248" y="419" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">classic_diagnosti...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-44"><g id="cell-cyVkqPuj_zZxdIbUwScy-44" content="<object label="sovd_client" score-type="component"/>" data-label="sovd_client" data-score-type="component"><g><rect x="20" y="529.37" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 559px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">sovd_client</div></div></div></foreignObject><text x="85" y="565" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">sovd_client</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-45"><g id="cell-cyVkqPuj_zZxdIbUwScy-45"><g><rect x="20" y="455.62" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 486px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">uds2sovd_<div>proxy</div></div></div></div></foreignObject><text x="85" y="491" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">uds2sovd_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-46"><g id="cell-cyVkqPuj_zZxdIbUwScy-46" content="<object label="diagnostic_&lt;div&gt;service_app&lt;/div&gt;" score-type="component"/>" data-label="diagnostic_<div>service_app</div>" data-score-type="component"><g><rect x="165" y="455.62" width="165" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 163px; height: 1px; padding-top: 486px; margin-left: 166px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">diagnostic_<div>service_app</div></div></div></div></foreignObject><text x="248" y="491" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">diagnostic_...</text></switch></g></g></g></g><g data-cell-id="cyVkqPuj_zZxdIbUwScy-48"><g id="cell-cyVkqPuj_zZxdIbUwScy-48" content="<object label="someip" score-type="external-module"/>" data-label="someip" data-score-type="external-module"><g><rect x="0" y="670" width="340" height="250" rx="37.5" ry="37.5" fill="#f5f5f5" stroke="#666666" pointer-events="all" style="fill: rgb(245, 245, 245); stroke: rgb(102, 102, 102);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 338px; height: 1px; padding-top: 677px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">someip</div></div></div></foreignObject><text x="170" y="697" fill="#333333" font-family=""Helvetica"" font-size="20px" text-anchor="middle">someip</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-4"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-4" content="<object label="score_someip_&lt;div&gt;gateway&lt;/div&gt;" score-type="component"/>" data-label="score_someip_<div>gateway</div>" data-score-type="component"><g><rect x="20" y="720" width="150" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 750px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">score_someip_<div>gateway</div></div></div></div></foreignObject><text x="95" y="756" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">score_someip_...</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-5"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-5" content="<object label="someip_&lt;div&gt;protocol&lt;/div&gt;" score-type="component"/>" data-label="someip_<div>protocol</div>" data-score-type="component"><g><rect x="20" y="791.56" width="150" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all" style="fill: rgb(245, 245, 245); stroke: rgb(102, 102, 102);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 148px; height: 1px; padding-top: 822px; margin-left: 21px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">someip_<div>protocol</div></div></div></div></foreignObject><text x="95" y="828" fill="#333333" font-family=""Helvetica"" font-size="20px" text-anchor="middle">someip_...</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-7"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-7" content="<object label="abi-compatible-datatypes" score-type="component"/>" data-label="abi-compatible-datatypes" data-score-type="component"><g><rect x="1230" y="830" width="160" height="60" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all" style="fill: rgb(218, 232, 252); stroke: rgb(108, 142, 191);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 158px; height: 1px; padding-top: 860px; margin-left: 1231px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">abi-compatible-datatypes</div></div></div></foreignObject><text x="1310" y="866" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">abi-compatible-d...</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-8"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-8" content="<object label="abi-compatible-datatypes" score-type="component"/>" data-label="abi-compatible-datatypes" data-score-type="component"><g><rect x="1580" y="910" width="145" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 143px; height: 1px; padding-top: 940px; margin-left: 1581px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">abi-compatible-datatypes</div></div></div></foreignObject><text x="1653" y="946" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">abi-compatible-...</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-9"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-9" content="<object label="ai-platform" score-type="module"/>" data-label="ai-platform" data-score-type="module"><g><rect x="1990" y="209.69" width="200" height="275.62" rx="30" ry="30" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 217px; margin-left: 1991px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">ai-platform</div></div></div></foreignObject><text x="2090" y="237" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">ai-platform</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-10"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-10" content="<object label="inference_&lt;div&gt;adapter&lt;/div&gt;" score-type="component"/>" data-label="inference_<div>adapter</div>" data-score-type="component"><g><rect x="2020" y="251.56" width="130" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 282px; margin-left: 2021px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">inference_<div>adapter</div></div></div></div></foreignObject><text x="2085" y="287" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="19px" text-anchor="middle">inference_...</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-15"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-15" content="<object label="onnx_runtime" score-type="component"/>" data-label="onnx_runtime" data-score-type="component"><g><rect x="2020" y="324.06" width="130" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all" style="fill: rgb(245, 245, 245); stroke: rgb(102, 102, 102);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 354px; margin-left: 2021px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #333333; "><div style="display: inline-block; font-size: 19px; font-family: "Helvetica"; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">onnx_runtime</div></div></div></foreignObject><text x="2085" y="360" fill="#333333" font-family=""Helvetica"" font-size="19px" text-anchor="middle">onnx_runtime</text></switch></g></g></g></g><g data-cell-id="zOfhbxZQrp5VTqdj2Vb1-17"><g id="cell-zOfhbxZQrp5VTqdj2Vb1-17"><g><rect x="550" y="1170" width="130" height="60" rx="9" ry="9" fill="#f5f5f5" stroke="#666666" pointer-events="all" style="fill: rgb(245, 245, 245); stroke: rgb(102, 102, 102);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 1177px; margin-left: 551px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #333333; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: #333333; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">ext module/<div>repository</div></div></div></div></foreignObject><text x="615" y="1197" fill="#333333" font-family=""Helvetica"" font-size="20px" text-anchor="middle">ext module/...</text></switch></g></g></g></g><g data-cell-id="lLnuWv548SjsVmpskmR--0"><g id="cell-lLnuWv548SjsVmpskmR--0" content="<object label="datarouter" score-type="component"/>" data-label="datarouter" data-score-type="component"><g><rect x="1134" y="640" width="120" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 670px; margin-left: 1135px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">datarouter</div></div></div></foreignObject><text x="1194" y="676" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">datarouter</text></switch></g></g></g></g><g data-cell-id="lLnuWv548SjsVmpskmR--4"><g id="cell-lLnuWv548SjsVmpskmR--4" content="<object label="record/&lt;div&gt;replay&lt;/div&gt;" score-type="component"/>" data-label="record/<div>replay</div>" data-score-type="component"><g><rect x="535" y="388.44" width="120" height="60" fill="#fff2cc" stroke="#d6b656" pointer-events="all" style="fill: rgb(255, 242, 204); stroke: rgb(214, 182, 86);"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 418px; margin-left: 536px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">record/<div>replay</div></div></div></div></foreignObject><text x="595" y="424" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">record/...</text></switch></g></g></g></g><g data-cell-id="H0D6Iy5TQXu2IpcHdf1l-1"><g id="cell-H0D6Iy5TQXu2IpcHdf1l-1"><g><rect x="405" y="1300" width="125" height="60" fill="#ffffff" stroke="#000000" pointer-events="all" style="fill: light-dark(#ffffff, var(--ge-dark-color, #121212)); stroke: light-dark(rgb(0, 0, 0), rgb(255, 255, 255));"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 123px; height: 1px; padding-top: 1330px; margin-left: 406px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; color: #000000; "><div style="display: inline-block; font-size: 20px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">language to be defined</div></div></div></foreignObject><text x="468" y="1336" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="20px" text-anchor="middle">language to b...</text></switch></g></g></g></g><g data-cell-id="H0D6Iy5TQXu2IpcHdf1l-3"><g id="cell-H0D6Iy5TQXu2IpcHdf1l-3"><g><rect x="380" y="0" width="1220" height="100" fill="none" stroke="none" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1218px; height: 1px; padding-top: 50px; margin-left: 382px;"><div style="box-sizing: border-box; font-size: 0; text-align: left; color: #000000; "><div style="display: inline-block; font-size: 60px; font-family: "Helvetica"; color: light-dark(#000000, #ffffff); line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Modules and Components of S-CORE 1.0</div></div></div></foreignObject><text x="382" y="68" fill="light-dark(#000000, #ffffff)" font-family=""Helvetica"" font-size="60px">Modules and Components of S-CORE 1.0</text></switch></g></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/docs/modules/index.rst b/docs/modules/index.rst index e63904f9fc..5b67d461d7 100644 --- a/docs/modules/index.rst +++ b/docs/modules/index.rst @@ -17,10 +17,16 @@ Modules ======= +.. image:: _assets/module_architecture.drawio.svg + :alt: Module Architecture + + .. note:: For now, we store the modules documentation in the modules tree, because multi-repo docs are not yet supported. Once this support becomes available it will be moved to the right repo. + + .. toctree:: :maxdepth: 1 :glob: From b44951360d805b1d1f3d9e2c96aae472c5c6d292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Thu, 31 Jul 2025 10:44:09 +0200 Subject: [PATCH 100/102] Adapt Score to Docs-As-Code 1.0 Release (#1529) --- .bazelversion | 2 +- .github/workflows/docs.yml | 2 +- BUILD | 8 +++ MODULE.bazel | 4 +- docs/BUILD | 51 ------------------- docs/conf.py | 2 + .../modules/feo/docs/manual/safety_manual.rst | 2 +- 7 files changed, 15 insertions(+), 56 deletions(-) delete mode 100644 docs/BUILD diff --git a/.bazelversion b/.bazelversion index ba7f754d0c..2bf50aaf17 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -7.4.0 +8.3.0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 21b9c641d6..1e203e3ae7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -55,7 +55,7 @@ jobs: run: sudo apt update && sudo apt install -y graphviz - name: Build documentation run: | - bazel run //docs:incremental_release -- --github_user=${{ github.repository_owner }} --github_repo=${{ github.event.repository.name }} + bazel run //:docs -- --github_user=${{ github.repository_owner }} --github_repo=${{ github.event.repository.name }} tar -cf github-pages.tar _build # ------------------------------------------------------------------------------ # Generate a unique artifact name to ensure proper tracking in all scenarios diff --git a/BUILD b/BUILD index 07e273b95a..f3086ae564 100644 --- a/BUILD +++ b/BUILD @@ -13,6 +13,7 @@ load("@score_cli_helper//:cli_helper.bzl", "cli_helper") load("@score_cr_checker//:cr_checker.bzl", "copyright_checker") +load("@score_docs_as_code//:docs.bzl", "docs") load("@score_starpls_lsp//:starpls.bzl", "setup_starpls") test_suite( @@ -61,3 +62,10 @@ setup_starpls( name = "starpls_server", visibility = ["//visibility:public"], ) + +docs( + data = [ + "@score_process//:needs_json", + ], + source_dir = "docs", +) diff --git a/MODULE.bazel b/MODULE.bazel index fe5a6d50ad..8a3889fabe 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -97,5 +97,5 @@ bazel_dep(name = "score_cli_helper", version = "0.1.1") bazel_dep(name = "score_starpls_lsp", version = "0.1.0") # Checker rule for CopyRight checks/fixs -bazel_dep(name = "score_docs_as_code", version = "0.4.4") -bazel_dep(name = "score_process", version = "1.0.4") +bazel_dep(name = "score_docs_as_code", version = "1.0.1") +bazel_dep(name = "score_process", version = "1.1.0") diff --git a/docs/BUILD b/docs/BUILD deleted file mode 100644 index b227440a89..0000000000 --- a/docs/BUILD +++ /dev/null @@ -1,51 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2024 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* - -load("@rules_pkg//pkg:mappings.bzl", "pkg_files") -load("@rules_pkg//pkg:tar.bzl", "pkg_tar") -load("@score_docs_as_code//:docs.bzl", "docs") - -# Creates all documentation targets: -# - `docs:incremental` for building docs incrementally at runtime -# - `docs:live_preview` for live preview in the browser without an IDE -# - `docs:ide_support` for creating python virtualenv for IDE support -# - `docs:docs` for building documentation at build-time - -docs( - conf_dir = "docs", - docs_targets = [ - { - "suffix": "latest", # latest main branch documentation build - "external_needs_info": [ - { - "base_url": "https://eclipse-score.github.io/process_description/main", - "json_url": "https://eclipse-score.github.io/process_description/main/needs.json", - "id_prefix": "process_", - }, - ], - }, - { - "suffix": "release", # latest main branch documentation build - "target": ["@score_process//process:docs_needs_latest"], - "external_needs_info": [ - { - "base_url": "https://eclipse-score.github.io/process_description/main", - "json_path": "/score_process~/process/docs_needs_latest/_build/needs/needs.json", - "id_prefix": "process_", - }, - ], - }, - ], - source_dir = "docs", - source_files_to_scan_for_needs_links = [], -) diff --git a/docs/conf.py b/docs/conf.py index 43b53ab640..923b5d867e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,6 +23,8 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "S-CORE" +project_url = "https://eclipse-score.github.io/score" +project_prefix = "S-CORE_" author = "S-CORE" release = "0.1" diff --git a/docs/modules/feo/docs/manual/safety_manual.rst b/docs/modules/feo/docs/manual/safety_manual.rst index 94b8fbbf1f..9054d888ef 100644 --- a/docs/modules/feo/docs/manual/safety_manual.rst +++ b/docs/modules/feo/docs/manual/safety_manual.rst @@ -95,7 +95,7 @@ Assumptions on the Environment - std::vec::Vec **Note:** The above list is not yet complete. It needs to be refined based on a final implementation. - At the moment, it covers probably about 95% of std library usages. + At the moment, it covers approximately 95% of std library usages. An accurate list could be determined by switching feo to #![no_std] and looking at the compilation errors, but it gets quickly out of date with a changing codebase. From a89d2549f820da9d28481efd4b8f9555ddb3d243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Thu, 31 Jul 2025 12:51:02 +0200 Subject: [PATCH 101/102] Fixing rst errors & Upgrading README & version (#1532) Recent upgrade was missing a commit with RST changes => here included. Changed the README to reflect new commands Updated versions to prepare for new release --- MODULE.bazel | 4 +- README.md | 78 ++++++------------- docs/contribute/general/folder.rst | 4 +- .../ipc/docs/safety_planning/index.rst | 2 +- .../quality_management.rst | 18 ++--- .../software_verification.rst | 4 +- 6 files changed, 39 insertions(+), 71 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 8a3889fabe..8bb8b2a1e3 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -13,7 +13,7 @@ module( name = "score_platform", - version = "1.0.1", + version = "1.1.0", compatibility_level = 0, ) @@ -73,7 +73,7 @@ bazel_dep(name = "rules_java", version = "8.13.0") # ############################################################################### -bazel_dep(name = "score_python_basics", version = "0.3.3") +bazel_dep(name = "score_python_basics", version = "0.3.4") ############################################################################### # diff --git a/README.md b/README.md index adfb454304..3dfaea8d2f 100644 --- a/README.md +++ b/README.md @@ -27,75 +27,44 @@ bazel run //:copyright.fix ### Building Documentation -Score supports multiple methods for generating documentation, tailored to different workflows: -1. **Bazel-based builds** for clean, sandboxed outputs. -2. **Incremental builds** for quick iterations during development. +Score supports multiple methods for generating documentation, tailored to different workflows: +1. **Documentation builds** for building the documentation. +2. **IDE independent live preview** for live previews of documentation without IDE integration. 3. **IDE integration** for live previews, live warnings and even faster iterations. -4. **IDE independent live preview** for live previews of documentation without IDE integration. - -#### Bazel-based Build - -This method ensures clean and isolated documentation builds in a controlled Bazel environment. -It is best suited for CI pipelines or production-ready outputs, although it takes longer compared to -incremental builds. -Here it is possible to build it either with the current 'main' branch of [process](https://github.com/eclipse-score/process_description) or with the imported release version of it. - - -> Note: 'latest' might not work if it's executed behind a proxy or vpn. If this is the case please use 'release' ```sh -bazel build //docs:docs_latest # use current main branch of imported docs repositories (e.g. process_description) -bazel build //docs:docs_release # use release version imported in MODULE.bazel +bazel run //:docs ``` -The output will be located here,depending on which way was chosen: -- bazel-bin/docs/docs_latest/_build/html. -- bazel-bin/docs/docs_release/_build/html. +The output will be located in `_build` +#### IDE independent live preview -#### Incremental build - -For local changes and faster feedback, use the incremental build. -This method generates the documentation directly in the _build directory. - +For a documentation live preview independent of an IDE (CLI + browser only), `sphinx-autobuild` can be used. +This will automatically rebuild the preview after save and have it available at `http://127.0.0.1:8000` ```sh -bazel run //docs:incremental_latest # use current main branch of imported docs repositories (e.g. process_description) -bazel run //docs:incremental_release # use release version imported in MODULE.bazel +bazel run //:live_preview ``` -Unlike IDE integration, which renders only the current file, this approach is ideal for quickly -verifying edits across the entire documentation during development. - #### IDE integration -For live previews, warnings, and linting during development, -integrate Esbonio with your IDE (e.g., VS Code): +For live previews, warnings, and linting during development, integrate Esbonio with your IDE (e.g., VS Code): ```sh -bazel run //docs:ide_support +bazel run //:ide_support ``` VS Code: Install the Esbonio extension in VS Code. After installation, restart your IDE. -You should now have live preview available when you open a `.rst` file. -Note: if the extension was already installed when you ran the `ide_support` command, -you will need to restart your IDE. +You should now have live preview available when you open a `.rst` file. -For features like type detection in conf.py or extensions, -point your IDE to the .venv_docs virtual environment. +> Note: if the extension was already installed when you ran the `ide_support` command, +you will need to restart your IDE. +For features like type detection in conf.py or extensions, +point your IDE to the .venv_docs virtual environment. Re-run //docs:ide_support if you update Sphinx extensions or other dependencies. -#### IDE independent live preview - -For a documentation live preview independent of an IDE (CLI + browser only), `sphinx-autobuild` can be used. -This will automatically rebuild the preview after save and have it available at http://127.0.0.1:8000 -Release and latest are both available here as well. -```sh -bazel run //docs:live_preview_latest # use current main branch of imported docs repositories (e.g. process_description) -bazel run //docs:live_preview_release # use release version imported in MODULE.bazel -``` - ### Testing @@ -116,8 +85,9 @@ Grouping of tests via tags is also supported: ```sh $ bazel test --test_tag_filters=docs-build ``` -You can add as many tags as you like, as long as a test has at least one of the tags it will be executed. -*Note: In order for a test to be picked up by this it has to be marked with the tag. Read more [here](/tools/testing/pytest/README.md) +You can add as many tags as you like, as long as a test has at least one of the tags it will be executed. + +> *Note: In order for a test to be picked up by this it has to be marked with the tag. Read more [here](/tools/testing/pytest/README.md) ### Test coverage for Python @@ -126,7 +96,7 @@ To generate coverage data for Python test targets, run the following command: ```sh bazel coverage --combined_report=lcov //docs:score_metamodel_test ``` -This generates a coverage file `_coverage_report.dat` in the folder `bazel-out/_coverage` for the Python test target `//docs:score_metamodel_test`. +This generates a coverage file `_coverage_report.dat` in the folder `bazel-out/_coverage` for the Python test target `//docs:score_metamodel_test`. Replace the target to execute coverage for a different test target. You can use the tool `genhtml` to generate an HTML report as follows: @@ -135,7 +105,7 @@ genhtml --ignore-errors mismatch --branch-coverage --output genhtml "$(bazel inf ``` This generates an HTML report in the folder `genhtml` which shows both line and branch coverage. Open file `genhtml/index.html` in a browser to show the report. -The tool `genhtml` is part of the `lcov` toolchain (https://github.com/linux-test-project/lcov). +The tool `genhtml` is part of the `lcov` toolchain (https://github.com/linux-test-project/lcov). You can install it on Debian/Ubuntu system as follows: ```sh sudo apt update @@ -145,13 +115,11 @@ sudo apt install lcov ### Notes #### Output Locations -* Bazel builds output, depending on which build was chosen: - - bazel-bin/docs/docs_latest/_build/html. - - bazel-bin/docs/docs_release/_build/html. +* Bazel builds output in the `_build` directory (cmd: `bazel run //:docs`) * Incremental builds output to _build, regardless of chosen way. #### Troubleshooting * Restart your IDE if live previews or warnings are not working after running ide_support. * Ensure your virtual environment is up-to-date by re-running //docs:ide_support when dependencies change. -* Ensure you ran //docs:ide_support before executing //:format.check or //:format.fix +* Ensure you ran //:ide_support before executing //:format.check or //:format.fix diff --git a/docs/contribute/general/folder.rst b/docs/contribute/general/folder.rst index 8934271053..1ae185c984 100644 --- a/docs/contribute/general/folder.rst +++ b/docs/contribute/general/folder.rst @@ -31,7 +31,7 @@ The following shows the folder structure of the platform repository (ordered alp docs/ -> Documentation of the feature architecture/ -> Feature architecture [:need:`PROCESS_wp__feature_arch`] requirements/ -> Feature requirements [:need:`PROCESS_wp__requirements__feat`] - safety_analysis/ -> Safety analysis on feature level [:need:`PROCESS_wp__feature_safety_analysis`] + safety_analysis/ -> Safety analysis on feature level [:need:`PROCESS_wp__feature_fmea`, :need:`PROCESS_wp__feature_dfa`, :need:`PROCESS_wp__platform_dfa`] safety_planning/ -> Feature specific safety workproducts planning verification/ -> Feature verification report (reporting all feature verifications) [:need:`PROCESS_wp__verification__platform_ver_report`] @@ -102,7 +102,7 @@ The modules and components shall follow the folder structure which was presented [:need:`PROCESS_wp__component_arch`]. requirements/ -> Component requirements [:need:`PROCESS_wp__requirements__comp`] safety_analysis/ -> Safety analysis on component level - [:need:`PROCESS_wp__sw_component_safety_analysis`] + [:need:`PROCESS_wp__sw_component_fmea`, :need:`PROCESS_wp__sw_component_dfa` ] verification/ -> Architecture review [:need:`PROCESS_wp__sw_arch_verification`], code inspection [:need:`PROCESS_wp__sw_implementation_inspection`] <lower_level_comp>/ -> Lower level component following <component_name> folder structure diff --git a/docs/features/communication/ipc/docs/safety_planning/index.rst b/docs/features/communication/ipc/docs/safety_planning/index.rst index c60d1fc885..2ba14afe36 100644 --- a/docs/features/communication/ipc/docs/safety_planning/index.rst +++ b/docs/features/communication/ipc/docs/safety_planning/index.rst @@ -58,7 +58,7 @@ Inter-process Communication Safety Work Products - :doc:`../architecture/index` - see below - * - :need:`PROCESS_wp__feature_safety_analysis` + * - :need:`PROCESS_wp__feature_fmea`, :need:`PROCESS_wp__feature_dfa` - <link to process> - <automated> - <link to issue> diff --git a/docs/platform_management_plan/quality_management.rst b/docs/platform_management_plan/quality_management.rst index aa68ca430e..db68003b5e 100644 --- a/docs/platform_management_plan/quality_management.rst +++ b/docs/platform_management_plan/quality_management.rst @@ -372,13 +372,6 @@ None - <Link to WP> - <automated> - * - :need:`PROCESS_wp__feature_safety_analysis` - - :need:`PROCESS_gd_guidl__safety_analysis` - - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` - - <Link to issue> - - <Link to WP> - - <automated> - * - :need:`PROCESS_wp__module_safety_manual` - :need:`PROCESS_gd_guidl__saf_plan_definitions` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__saf_plan_definitions')` @@ -414,7 +407,7 @@ None - <Link to WP> - <automated> - * - :need:`PROCESS_wp__platform_feature_dfa` + * - :need:`PROCESS_wp__platform_dfa` - :need:`PROCESS_gd_guidl__safety_analysis` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` - <Link to issue> @@ -582,7 +575,14 @@ None - <Link to WP> - <automated> - * - :need:`PROCESS_wp__sw_component_safety_analysis` + * - :need:`PROCESS_wp__sw_component_fmea` + - :need:`PROCESS_gd_guidl__safety_analysis` + - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` + - <Link to issue> + - <Link to WP> + - <automated> + + * - :need:`PROCESS_wp__sw_component_dfa` - :need:`PROCESS_gd_guidl__safety_analysis` - :ndf:`copy('status', need_id='PROCESS_gd_guidl__safety_analysis')` - <Link to issue> diff --git a/docs/platform_management_plan/software_verification.rst b/docs/platform_management_plan/software_verification.rst index e0ade6494a..cf14f98782 100644 --- a/docs/platform_management_plan/software_verification.rst +++ b/docs/platform_management_plan/software_verification.rst @@ -325,8 +325,8 @@ Beside :need:`PROCESS_wp__verification__comp_int_test` and :need:`PROCESS_wp__ve following aspects define the coverage of the architectural design. - :need:`PROCESS_wp__sw_arch_verification` - done by walkthrough (QM) or inspection (safety-critical parts) -- :need:`PROCESS_wp__sw_component_safety_analysis` for safety-critical parts -- :need:`PROCESS_wp__feature_safety_analysis` for safety-critical parts +- :need:`PROCESS_wp__sw_component_fmea` and :need:`PROCESS_wp__sw_component_dfa` for safety-critical parts +- :need:`PROCESS_wp__feature_fmea` and :need:`PROCESS_wp__feature_dfa` for safety-critical parts Each architectural element has at least one test case linked with attribute "fully verified" or multiple test cases with attribute "partially verified". From 5602e9fbe4a8dc60e86e36ee918397e0b997da2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20S=C3=B6ren=20Pollak?= <maximilian.pollak@expleogroup.com> Date: Thu, 31 Jul 2025 14:04:41 +0200 Subject: [PATCH 102/102] Fix versioning (#1535) --- MODULE.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index 8bb8b2a1e3..dbbb25da56 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -13,7 +13,7 @@ module( name = "score_platform", - version = "1.1.0", + version = "0.3.0", compatibility_level = 0, )