diff --git a/bazel/rules/rules_score/BUILD b/bazel/rules/rules_score/BUILD index a2f2c513..d818c3b2 100644 --- a/bazel/rules/rules_score/BUILD +++ b/bazel/rules/rules_score/BUILD @@ -213,6 +213,8 @@ sphinx_module( "docs/**/*.rst", "docs/**/*.puml", "docs/**/*.md", + "docs/**/*.svg", + "docs/**/*.png", ], allow_empty = True, ) + [ diff --git a/bazel/rules/rules_score/docs/_assets/SEooC_Overview.drawio.svg b/bazel/rules/rules_score/docs/_assets/SEooC_Overview.drawio.svg new file mode 100644 index 00000000..6936c4ad --- /dev/null +++ b/bazel/rules/rules_score/docs/_assets/SEooC_Overview.drawio.svg @@ -0,0 +1,4 @@ + + + +
SEooC
SEooC
Public API
Public API
Certified Scope
Certified Scope
AoUs
AoUs
Assumed
System
Requirements
Assumed...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/bazel/rules/rules_score/docs/_assets/SeoocExample_InternalApi.puml b/bazel/rules/rules_score/docs/_assets/SeoocExample_InternalApi.puml index cba23b05..4ca1753b 100644 --- a/bazel/rules/rules_score/docs/_assets/SeoocExample_InternalApi.puml +++ b/bazel/rules/rules_score/docs/_assets/SeoocExample_InternalApi.puml @@ -16,7 +16,7 @@ namespace safety_software_seooc_example { namespace component_example { interface "InternalInterface" as InternalInterface <>{ - {abstract} GetData(BindingType binding): Data* + {abstract} GetData() } } } diff --git a/bazel/rules/rules_score/docs/_assets/SeoocExample_PublicApi.puml b/bazel/rules/rules_score/docs/_assets/SeoocExample_PublicApi.puml index 444a5f24..129d062e 100644 --- a/bazel/rules/rules_score/docs/_assets/SeoocExample_PublicApi.puml +++ b/bazel/rules/rules_score/docs/_assets/SeoocExample_PublicApi.puml @@ -13,9 +13,10 @@ @startuml SeoocExample_PublicApi -package "SampleLibraryAPI" as SampleLibraryAPI { - interface "GetNumber" as GetNumber - ' interface "SetNumber" as SetNumber +namespace safety_software_seooc_example { + interface "SampleLibraryAPI" as SampleLibraryAPI { + + GetNumber() + } } @enduml diff --git a/bazel/rules/rules_score/docs/_assets/SeoocExample_StaticDesign.puml b/bazel/rules/rules_score/docs/_assets/SeoocExample_StaticDesign.puml index 499eefbe..687e16ae 100644 --- a/bazel/rules/rules_score/docs/_assets/SeoocExample_StaticDesign.puml +++ b/bazel/rules/rules_score/docs/_assets/SeoocExample_StaticDesign.puml @@ -25,8 +25,8 @@ package "Safety Software SEooC Example" as safety_software_seooc_example < SampleLibraryAPI +safety_software_seooc_example )-d- SampleLibraryAPI @enduml diff --git a/bazel/rules/rules_score/docs/_assets/assumed_layered_software_architecture.drawio.svg b/bazel/rules/rules_score/docs/_assets/assumed_layered_software_architecture.drawio.svg new file mode 100644 index 00000000..d94d032b --- /dev/null +++ b/bazel/rules/rules_score/docs/_assets/assumed_layered_software_architecture.drawio.svg @@ -0,0 +1,4 @@ + + + +
QNX Operating System
QNX Operating System
App 1
App 1
App 2
App 2
App 3
App 3
SEooC
SEooC
Text is not SVG - cannot display
\ No newline at end of file diff --git a/bazel/rules/rules_score/docs/_assets/scope_check.puml b/bazel/rules/rules_score/docs/_assets/scope_check.puml new file mode 100644 index 00000000..898dfe99 --- /dev/null +++ b/bazel/rules/rules_score/docs/_assets/scope_check.puml @@ -0,0 +1,39 @@ +' ******************************************************************************* +' Copyright (c) 2026 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 scope_check + +skinparam defaultTextAlignment center +skinparam ArrowFontSize 10 +skinparam packageStyle rectangle +hide stereotype + +package "dependable_element" as de { + rectangle "unit MyUnit\nscope = [\"//third_party/foo:__subpackages__\"]" as MyUnit + + rectangle "//pkg:my_unit_lib\n(implementation)" as impl #LightBlue + rectangle "//third_party/foo/bar:baz\n(transitive dep)" as instscope #LightGreen + rectangle "//other/unrelated:thing\n(transitive dep)" as outofscope #Pink + + MyUnit -down-> impl + impl -down-> instscope : in certified scope + impl -down-> outofscope : NOT in any certified scope +} + +note bottom of outofscope + Rejected: "Not in certified scope + //third_party/foo:__subpackages__, + stopping at other" +end note + +@enduml diff --git a/bazel/rules/rules_score/docs/_assets/seooc_validation.puml b/bazel/rules/rules_score/docs/_assets/seooc_architecture_validation.puml similarity index 100% rename from bazel/rules/rules_score/docs/_assets/seooc_validation.puml rename to bazel/rules/rules_score/docs/_assets/seooc_architecture_validation.puml diff --git a/bazel/rules/rules_score/docs/index.rst b/bazel/rules/rules_score/docs/index.rst index a5e6de94..41ba117a 100644 --- a/bazel/rules/rules_score/docs/index.rst +++ b/bazel/rules/rules_score/docs/index.rst @@ -12,23 +12,16 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -SCORE Rules for Bazel +Rules SCORE for Bazel ===================== -``rules_score`` provides Bazel build rules for structuring and documenting -safety-critical software according to S-CORE process guidelines. It covers -the full artefact lifecycle — from requirements and architecture through -safety analysis to the top-level SEooC assembly. - -.. toctree:: - :maxdepth: 2 - :caption: Overview - - overview +.. include:: overview.rst + :start-line: 14 .. toctree:: :maxdepth: 2 :caption: Usage + :hidden: skills_setup user_guide/index @@ -37,6 +30,7 @@ safety analysis to the top-level SEooC assembly. .. toctree:: :maxdepth: 2 :caption: Validation + :hidden: tool_reference/specs/bazel_component tool_reference/specs/class_design_implementation @@ -48,6 +42,7 @@ safety analysis to the top-level SEooC assembly. .. toctree:: :maxdepth: 2 :caption: Development + :hidden: integration_guide tooling_architecture @@ -56,6 +51,7 @@ safety analysis to the top-level SEooC assembly. .. toctree:: :maxdepth: 2 :caption: Tool Qualification + :hidden: Requirements Traceability Report diff --git a/bazel/rules/rules_score/docs/overview.rst b/bazel/rules/rules_score/docs/overview.rst index c4a24f16..a2ef3241 100644 --- a/bazel/rules/rules_score/docs/overview.rst +++ b/bazel/rules/rules_score/docs/overview.rst @@ -15,32 +15,190 @@ Overview ======== -``rules_score`` organises safety-critical software artefacts into four groups: +What is a Dependable Element? +------------------------------ -**Documentation Rules** — Sphinx builder and supporting helpers: +A :ref:`dependable_element ` assembles the framework of a +**Safety Element out of Context (SEooC)** as defined by ISO 26262 — a safety +element that is developed and verified independently of a concrete project. This means that +it provides both an implementation and the required safety documents and artifacts +for a specific safety-relevant function. -- :ref:`sphinx_module ` — Builds Sphinx HTML from RST/MD sources with dependency merging -- :ref:`filter_execpath ` — Resolves a build output path into a Sphinx ``-D`` flag at analysis time *(advanced)* +To enable this, assumptions on the surrounding system (context) must be taken. Those +assumptions are captured as :ref:`assumed_system_requirements `. +In Combination with the Assumed System, the inputs to the dependable element are defined: -**Artifact Rules** — declare individual process work products: +.. image:: _assets/assumed_layered_software_architecture.drawio.svg + :alt: Layered software architecture with assumed system requirements + :align: center + :width: 60% -- :ref:`assumed_system_requirements ` — System-level requirements received from the wider context -- :ref:`feature_requirements ` — High-level feature specifications -- :ref:`component_requirements ` — Component-level requirements -- :ref:`assumptions_of_use ` — Safety-relevant operating conditions imposed on the integrator -- :ref:`glossary ` — Glossary pages included in the generated documentation -- :ref:`architectural_design ` — Software architecture (static, dynamic, public API) -- :ref:`unit_design ` — Code-level design diagrams scoped to a single unit -- :ref:`fmea ` — Failure Mode and Effects Analysis (failure modes, FTA, control measures) -- :ref:`dependability_analysis ` — Complete safety analysis wrapping one or more FMEA targets +But not everything can be guaranteed by the element's own implementation +— whatever falls outside its scope of responsibility (or cannot be implemented +by the element itself) is instead exposed as +Assumptions of Use that the integrating project must satisfy. It is the same for the other +SEooCs that the dependable element itself depends on. The SEooCs which are integrated also provide their own Assumptions of Use, which either must be satisfied or forwarded to the next level of integration. -**Structural Rules** — wire artefacts into a verifiable SEooC: +Alongside the context for documentation a context for the source files also needs to be defined. This +is achieved by exposing also the covered sources files as bazel scope. So on a top level +it can be verified that each dependency which is used in the project is also covered by a dependable element. -- :ref:`unit ` — Smallest testable software element (design + implementation + tests) -- :ref:`component ` — Collection of units providing specific functionality -- :ref:`dependable_element ` — Complete SEooC with all artefacts assembled and validated +On an abstract level, a SEooC therefore exposes following interfaces to the outside world: + +.. image:: _assets/SEooC_Overview.drawio.svg + :alt: Overview of a SEooC's interfaces + :align: center + :width: 60% + +See :doc:`user_guide/general` for the underlying concept. + +Concept Behind Rules SCORE +-------------------------- + +``rules_score`` keep requirements, architecture and safety analysis as plain files living next to +implementation and tests which they describe. Traceability between the distinct files is performed +in Bazel as the Buildsystem using the bazel dependency graph itself: + +an ``architectural_design`` target only +"knows" about the ``unit``/``component`` targets it lists, a ``unit`` only +compiles the ``implementation`` files it declares, and a ``dependable_element`` +only assembles the targets reachable through its own attributes. + +Every ``.. uml::`` diagram, ``.trlc`` requirement, and safety-analysis file is a build input +like any other source file, so any change to it is picked up by the next ``bazel +build``/``bazel test`` automatically - using bazel caching for efficient builds. + +This file-based, build-intrinsic approach gives two things for free that a +separate documentation/traceability tool would otherwise have to reconstruct: + +- **Consistency at build time** — see :ref:`Automatic Checks ` + below: because every artefact is a target, Bazel already knows exactly which + units, components, and diagrams belong together, so cross-checking them is + just another build/test action. +- **Leverage Bazel Action Graph** — because every check is an ordinary action + with declared inputs/outputs, Bazel's incremental build and (remote) caching + apply to it just like to a compile step: changing one requirement file only + re-runs the validations whose inputs actually changed, unaffected + units/components are served from cache, and the same graph scales to remote + execution without any extra plumbing. + +.. _automatic-checks: + +Automatic Checks +----------------- + +Requirements (test) +~~~~~~~~~~~~~~~~~~~~ + +For every ``assumed_system_requirements``/``feature_requirements``/``component_requirements`` +target two layers of checks apply: + +- **TRLC intrinsic checks** — syntax errors, wrong field types, missing mandatory + fields, unknown fields, enum/array-cardinality violations, and broken + cross-references including versioning +- **S-CORE requirements model** enforces the + derivation chain ``AssumedSystemReq → FeatReq → CompReq``, requires an ``Asil`` safety + classification and defines the safety-analysis + vocabulary (``FailureMode`` with HAZOP ``Guideword``\ s, ``ControlMeasure``, + ``AoU``) used by ``fmea``/``assumptions_of_use``. + +Architecture consistency (build) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Four design layers are cross-checked against each other and against the actual +Bazel/C++ implementation: + +.. uml:: _assets/seooc_architecture_validation.puml + :align: center + :width: 100% + +- **Bazel ↔ static design** — every ``component``/``unit`` target must appear in + the static PlantUML diagram and vice versa + (:doc:`spec `). +- **Static ↔ public/internal API** — interfaces referenced in the static design + must be declared by the public/internal API class diagrams + (:doc:`public API spec `, + :doc:`internal API spec `). +- **Static ↔ dynamic design** — sequence-diagram participants and interface + connections must match the static design's units and their interfaces + (:doc:`spec `). +- **Dynamic ↔ internal API** — every sequence-diagram call must exist on the + target interface (including cross-unit call roles); interface methods should + be exercised somewhere + (:doc:`spec `). +- **Design ↔ implementation** — unit design class diagrams (types, members, + methods, enum literals, relationships) must match the generated C++ + implementation model + (:doc:`spec `). +- **Public API ↔ failure modes** — every public API interface item must be + referenced by a ``FailureMode`` (via ``FailureMode.interface``) in the + SEooC's own safety analysis; unreferenced interfaces fail traceability + (:doc:`spec `). + +Certified scope (build) +~~~~~~~~~~~~~~~~~~~~~~~~ + +Every Bazel target transitively reachable through ``unit.implementation`` must +fall inside the package tree declared by this element's own ``unit``/``component`` +scope — uncertified external dependencies are rejected, and the same scope may +not be declared twice (:doc:`spec `). + +.. uml:: _assets/scope_check.puml + :align: center + :width: 100% + +Integrity level (build) +~~~~~~~~~~~~~~~~~~~~~~~~ + +A ``dependable_element`` must not depend (``deps``) on another with a *lower* +``integrity_level``. + +Test case coverage (build) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Every ``component`` can declare that its test cases completely cover its requirements. +Coverage is defined by commiting a lockfile containing all test specifications and requirement IDs. +During build it is validated that the test spec was not altered or links were changed. +(:doc:`spec `). + +Traceability (test) +~~~~~~~~~~~~~~~~~~~~ + +``bazel test`` runs ``lobster-ci-report`` over the merged requirement / +architecture / test / safety-analysis graph — assumed-system and feature +requirements, component requirements, architecture, public API, unit tests, +failure modes, control measures, root causes, and AoUs — and fails if any item +lacks full up/down traceability. + +.. graphviz:: + + digraph tracing_policy { + rankdir=TB; + node [shape=box, style=filled, fontname="Helvetica", margin="0.3,0.1"]; + edge [arrowhead=open]; + + "Feature Requirements" [fillcolor="#2196F3", fontcolor="white"]; + "Received AoUs" [fillcolor="#2196F3", fontcolor="white"]; + "Forwarded AoUs" [fillcolor="#2196F3", fontcolor="white"]; + "Component Requirements" [fillcolor="#2196F3", fontcolor="white"]; + "Unit Test" [fillcolor="#FF9800", fontcolor="white"]; + "Test Case Coverage" [fillcolor="#FF9800", fontcolor="white"]; + "Architecture" [fillcolor="#4CAF50", fontcolor="white"]; + "Public API" [fillcolor="#4CAF50", fontcolor="white"]; + "Failure Modes" [fillcolor="#2196F3", fontcolor="white"]; + "Control Measures" [fillcolor="#2196F3", fontcolor="white"]; + "Root Causes" [fillcolor="#FF9800", fontcolor="white"]; + "Forwarded AoUs" -> "Received AoUs"; + "Component Requirements" -> "Feature Requirements"; + "Component Requirements" -> "Received AoUs"; + "Unit Test" -> "Component Requirements"; + "Test Case Coverage" -> "Component Requirements"; + "Architecture" -> "Component Requirements"; + "Failure Modes" -> "Public API"; + "Root Causes" -> "Failure Modes"; + "Root Causes" -> "Control Measures"; + } -All rules support cross-module dependencies for sphinx-needs integration and HTML merging. Quick Reference --------------- diff --git a/bazel/rules/rules_score/docs/tool_reference/index.rst b/bazel/rules/rules_score/docs/tool_reference/index.rst index 69fac59c..06b10acf 100644 --- a/bazel/rules/rules_score/docs/tool_reference/index.rst +++ b/bazel/rules/rules_score/docs/tool_reference/index.rst @@ -41,6 +41,7 @@ of truth. validation_core Clickable PlantUML bazel + scope_check .. toctree:: :maxdepth: 1 diff --git a/bazel/rules/rules_score/docs/tool_reference/scope_check.rst b/bazel/rules/rules_score/docs/tool_reference/scope_check.rst new file mode 100644 index 00000000..e267fbfc --- /dev/null +++ b/bazel/rules/rules_score/docs/tool_reference/scope_check.rst @@ -0,0 +1,89 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 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 + # ******************************************************************************* + +Scope Check +=========== + +The scope check verifies that every Bazel target which ends up in a +``dependable_element``'s transitive implementation closure is covered by a +**certified scope** declared somewhere in that or another element. It catches the case +where a unit's implementation silently starts depending on code that nobody +certified. + +Declaring scope +---------------- + +Each ``unit`` declares the scope it certifies via its ``scope`` attribute — +labels, packages (``//some/package:__pkg__``), or packages-and-subpackages +(``//some/package:__subpackages__``), following normal Bazel visibility +patterns: + +.. code-block:: starlark + + unit( + name = "MyUnit", + implementation = [":my_unit_lib"], + scope = ["//third_party/foo:__subpackages__"], + unit_design = [":MyUnit_design"], + tests = [], + ) + +``scope`` is for dependencies that are *not* explicitly named as +``implementation`` targets themselves (e.g. third-party libraries pulled in +transitively) but are still known and accepted as part of the unit. Every +``unit`` and ``component`` also implicitly certifies its own explicitly named +targets (``implementation``, nested ``components``). + +Scopes are collected transitively: a ``component``'s certified scope is the +union of its own units' and nested components' scopes, and a +``dependable_element``'s certified scope is the union of all its components' +scopes plus any scopes brought in through ``deps`` on other dependable +elements. + +What is checked +---------------- + +For each ``unit``, an aspect (``cc_dependencies_aspect``) walks the +``deps`` / ``implementation_deps`` / ``exported_deps`` attributes of its +``implementation`` targets and collects every transitively reached label. +``dependable_element`` then checks each collected label against the tree of +certified scopes built from all ``scope`` declarations in the element: a +label is in scope if it (or an enclosing package / subpackage wildcard) was +declared somewhere. Any dependency that is not covered fails the check with: + +.. code-block:: text + + Not in certified scope