STIG Help

Model failure propagation

The Analysis viewpoint records engineering analysis for an element. For safety work, STIG structures this as element-level interface analysis, failure modes, safety measures, and typed propagation links. This model-level analysis is distinct from automated C/C++ data-flow analysis; the two meet in the generated report.

Structure the analysis

  • Analysis names the subject element and owns its interface-point analyses.

  • InterfacePointAnalysis identifies the modeled input or output and where it is used.

  • Failure records an exact failure mode, ASIL, severity, multiplicity, measures, and propagatesTo links.

  • SafetyMeasure links mitigation and verification intent back into the connected model.

When decomposing a port analysis, mirror its Context structure with an InterfacePointAnalysis for the port, containing one member analysis per analyzed endpoint. For example, declare outgoingPortAnalysis in the element's Analysis, then declare signalAnalysis inside it with interfacePoint = element.outgoingPort.signal. The port analysis references element.outgoingPort. Each member retains the enclosing element's ownerAnalysis; its failures belong to that member analysis. Checks and exports traverse the complete hierarchy.

A port or service-group analysis containing member analyses and no direct failures is decomposed: required usedIn, incoming contribution, and S10-failure completeness are checked on its members. Adding a direct failure also makes those completeness checks apply to the container itself. Authored references are still validated at every level; no parent links or failures are inferred from the containment.

InterfacePointAnalysis accepts no name, description, or asil constructor arguments. Its final name getter derives a label from the interface point: "${interfacePoint.name} analysis", or null if that name is absent or blank. Read description and classification from analysis.interfacePoint.description and analysis.interfacePoint.effectiveAsil. Supplying those constructor arguments or overriding the properties is a Kotlin compile error. Reading description or asil directly on an InterfacePointAnalysis is also a compile error; their final getters return null through the shared MetamodelEntity API.

The analysis keeps its canonical Kotlin identity and ownership. Its display label uses the referenced interface point's name followed by analysis, and its failure-ASIL, severity, and usedIn checks read interfacePoint.effectiveAsil. Use declaration documentation for analysis-specific explanation. The native exchange schema also excludes these three properties: remove them from existing interface-point-analysis JSON, including explicit null values. No metadata-null model rule is needed because the type prevents supplying or overriding the values.

An analysis may target a directly declared interface point, a service member accessed through .serviceInterface (including nested ServicePort groups), or a topic accessed through .topic. A shared definition can be analysed for each element whose ports use it; the enclosing Analysis.element identifies the element being analysed. A usedIn reference is interpreted in the source element's analysis parent: normally its direct parent, with the single-level bypass described below. Sharing a definition does not create incoming contributions to every analysis of that definition.

/** Failure analysis for braking stage decisions. */ class StageArrayAnalysis : InterfacePointAnalysis( interfacePoint = fusionActivity.stageArrayPublisher, usedIn = listOf(adCluster.brakingRequestPublisher), ) { val falsePositive = Failure( name = "Falsely active stage", description = "${fusionActivity.name} publishes an active stage on " + "${fusionActivity.stageArrayPublisher.name} although activation conditions are false.", asil = ASIL.B, severity = Severity.S10, multiplicity = Multiplicity.SINGLE_POINT, mitigatedBy = listOf(stageConditionGuard), propagatesTo = listOf(adAnalysis.unintendedBrakeRequest), ) } class FusionAnalysis : Analysis(name = "Fusion analysis", element = fusionActivity,) { val stageArray = StageArrayAnalysis() }

Use one precise failure per property. A propagation link means this failure can contribute to the linked failure; it does not by itself prove a feasible implementation path. Automated source analysis can provide that lower-level evidence when configured.

Record evaluation and supporting evidence

Use Failure.argument for the engineering reasoning behind the recorded evaluation: why the referenced measures or independent failures address the mode, or why a remaining contribution needs no further measure under the applicable criteria. State assumptions and reference supporting evidence. The property is nullable; recording an argument does not itself prove sufficiency or waive model checks. Use comment for unresolved review questions, finding details, action items and import notes. For example, a description of an independent hardware reaction belongs in argument; a request for the software team to establish whether that reaction exists belongs in comment. An argument can explain a technical gap as well as adequate coverage. Attach tracked findings through issues. Unresolved findings without a ticket should carry a visible project marker such as FIXME_JIRAID in the comment.

Conclude on each applicable software failure individually. SUFFICIENT can rely on justified architectural or process measures as well as safety mechanisms, with evidence of how those measures address that failure. A generic process claim or the percentage of other failure modes covered cannot close its gap. RESIDUAL identifies a remaining uncovered contribution or limitation supported by an engineering argument. For hardware, reference the aggregate analysis demonstrating the relevant targets; do not claim that a single failure establishes the totals. The same principle applies to justified system or software limitations without waiving applicable safety requirements.

Keep numerical coverage separate: Failure.diagnosticCoverage = 0.99f records 99% diagnostic coverage, and 1.0f means 100%; null means unspecified or not applicable. Construction rejects non-finite values and values outside 0.0f..1.0f. Record the calculation basis and evidence. This fraction is neither software test coverage nor the qualitative evaluation; no diagnostic-coverage sufficiency rules currently apply.

The FailureEvaluation API documentation gives the enum definitions and references to the AIAG & VDA FMEA Handbook, Bosch Booklet 14 and the STPA Handbook. These methods inform STIG's vocabulary without prescribing this enum. An issue link records tracked work; it does not establish effective measures, reduce problem severity or close a gap.

Analysis, InterfacePointAnalysis, and Failure implement SafetyAssessment, sharing nullable argument and evaluation properties. The evaluation vocabulary remains FailureEvaluation: SUFFICIENT, RESIDUAL, or GAP. An enabled analysis of a QM element may omit interface-point analyses when it records a nonblank argument and an evaluation, for example argument = "Element is QM." and evaluation = FailureEvaluation.SUFFICIENT. An empty analysis of a QM interface point likewise records argument = "Analysis not required for QM interface point" and its evaluation instead of inventing failure modes. Existing failures and member analyses remain valid; empty QM member analyses are checked individually. A recorded evaluation may identify a gap or residual contribution: the presence check does not assert sufficiency. These assessments are retained in Highway JSON, generated Kotlin, HTML, and MkDocs Markdown.

An interface-point analysis can record belongsToSafetyFunction = false when the assessed interface does not contribute to the architected safety functions in the applicable concept. Leave the flag unset or set it to true for interfaces requiring detailed analysis. QM classification independently exempts an interface from the usedIn and S10 completeness requirements; an unspecified ASIL is not QM. An explicit false likewise exempts those two requirements without changing ASIL, and requires a nonblank argument and an evaluation. For example, use argument = "Analysis not required for interface points not belonging to architected safety functions" and evaluation = FailureEvaluation.SUFFICIENT when that scope assessment is sufficient. A missing justification produces an assessment finding rather than a demand for invented failures or links. Each nested analysis retains its own scope decision. Existing failures and authored links remain subject to their consistency checks.

For example, assume Context declares myComponent.diagnosticStatus as ASIL.QM, and a reviewed scope assessment establishes that myComponent.serviceCounter does not contribute to architected safety functions. Both analyses can then be owned directly without declaring Failures. Replace the illustrative arguments with the actual assessment and supporting evidence for the project:

class MyComponentAnalysis : Analysis(element = myComponent) { val diagnosticStatus = InterfacePointAnalysis( interfacePoint = myComponent.diagnosticStatus, evaluation = FailureEvaluation.SUFFICIENT, argument = "The diagnostic status interface is classified QM in Context; detailed analysis is not required.", ) val serviceCounter = InterfacePointAnalysis( interfacePoint = myComponent.serviceCounter, belongsToSafetyFunction = false, evaluation = FailureEvaluation.SUFFICIENT, argument = "The reviewed safety concept assigns no architected safety function to this service counter.", ) } val myComponentAnalysis = MyComponentAnalysis()

QM classification does not automatically set belongsToSafetyFunction = false, and that flag does not change the interface point's ASIL. The val properties still support source-based UI editing, as explained under model instance identity and declaration provenance.

Declare each safety mechanism in the Design of the element that implements it and reference it through Failure.mitigatedBy. The implementing element may differ from the analyzed element. Preserve unresolved ownership as an explicit review item; a mechanism's name in prose does not establish its implementation or sufficiency.

Use Severity.S0 through Severity.S10 for severity classes; this is the preferred notation. Each constant stores the corresponding Float, so Severity.S10.value is 10.0f and Severity.S10 == Severity(10.0f). The explicit value constructor is also supported: Failure(severity = Severity(10.0f)). A bare severity = 10.0f is no longer accepted by Kotlin; wrap the value or select the corresponding constant. Missing severity remains null and is reported by failureSeverityDefined.

Severity.S1 through Severity.S10 also expose name and description for the automotive DFMEA effect scale: S10 concerns safety, S9 regulatory compliance, S8/S7 loss/degradation of primary driving function, S6/S5 loss/degradation of secondary function, S4–S2 objectionable appearance/sound/vibration/harshness/haptics, and S1 no discernible effect. These are value metadata, not registered model entities. S0 and noncanonical values have no assigned effect name or description. HTML tables show a colored sprite badge with the number and short name; the complete effect description is available on hover. Numeric storage, equality, and exchange remain unchanged.

The constructor preserves its Float without rounding, clamping, or rejecting it during model loading. The existing HIGH failureSeverityValue rule rejects non-finite values and values outside the inclusive ±0.01 band around an integer from 0 through 10, including Severity(10.5f). The tolerance affects only this validity check; propagation and name-suffix checks still compare the stored values. Canonical Highway JSON keeps severity as a nullable number, and generated Kotlin prefers named classes for exact values while preserving other values.

Cover the interface tree

interfacePointAnalysisCoverage checks every non-QM interface point belonging to a non-QM element, including definitions used through its ports. Unspecified ASIL is included. A point is covered when an enabled Analysis of that element contains an InterfacePointAnalysis for the point itself, an ancestor, or a descendant in its interface tree. Ancestors and descendants may be several levels away. Missing coverage is HIGH on the element's enabled Analysis, with the uncovered interface point retained as evidence. If the Analysis is absent, the element receives the finding. Coverage remains collective when several enabled Analyses describe one element; if none supplies coverage, the element receives the finding because there is no single Analysis container to identify as responsible.

For a tree port → service → method, an analysis on any one of those points covers the other points along that path. An analysis on one method does not cover a sibling method. Likewise, an analysis of one port does not cover a separate port merely because both use the same service definition. A selected member use retains its port identity, and an unselected member cannot cover that port. Shared service and topic definitions are evaluated separately for each owning element; an analysis of another element does not provide coverage.

Coverage checks the presence of an IPA; the existing ASIL, severity, S10 and mitigation rules check its content. QM elements need no interface-point analyses, and QM points need no individual coverage. An unknown ASIL on either the element or the point does not qualify for the QM exemption. The QM assessment rules above check explicitly declared analyses that omit detailed analysis.

If all declared analyses of an element have enabled = false, coverage is outside that element's analysis scope. When any analysis is enabled, only enabled analyses can supply coverage. An entirely absent Analysis leaves the interface points uncovered. Incomplete model context must be loaded before a missing-coverage conclusion is made. In a module check, coverage is evaluated for the checked elements, including their imported interface definitions and members. Other elements supplied only as context do not need complete analysis content for this rule.

Bypass one Analysis level

Analysis.enabled is nullable and defaults to null. An existing Analysis is enabled when this value is true or null; an empty enabled Analysis is not a bypass. If an element has no Analysis, or all its Analyses have enabled = false, its children bypass that Analysis level.

For e1 → c1 → gc1, where the arrows are parent-to-child relationships, disabling c1's Analysis means:

  • c1's disabled Analysis may retain InterfacePointAnalysis declarations. Disabling the level is a scope flag and does not itself produce a finding. Its Context interface points remain available.

  • gc1's InterfacePointAnalysis.usedIn targets interface points belonging to e1.

  • gc1's failures propagate to failures in an enabled Analysis of e1. The existing consistency rule still requires each target failure's analysed interface point to appear in the source interface-point analysis's usedIn.

  • e1 must have an enabled Analysis. Two consecutive absent or disabled Analysis levels are an error, not a request to search further ancestors. Missing module content is a loading error and cannot establish an absent Analysis.

For example, declare the bypass without adding interface-point analyses:

val c1Analysis = Analysis(name = "C1 analysis", element = c1, enabled = false)

This changes the engineering hierarchy for Analysis only. Gradle's modelCheck.analysis.enabled = false merely disables Analysis checks; it does not bypass a level. Requirements, Design, and Tests keep their existing semantics.

Declare model boundaries once per element

Element.isTopLevel and Element.isBottomLevel both default to false. They describe the assessed model scope and apply to every specification of that element. Set them from the intended scope; STIG never infers a boundary from an element type or from missing loaded children. The former assumed fields on specifications and individual entities are removed. Imported-evidence provenance does not establish a hierarchy boundary.

isTopLevel

isBottomLevel

Upward links

Incoming child analysis links

false

false

Required

Required

true

false

Expected absent

Required

false

true

Required

Expected absent

true

true

Expected absent

Expected absent

Upward analysis links are Failure.propagatesTo and InterfacePointAnalysis.usedIn. The latter targets an InterfacePoint, and its displayed inverse is uses. For every failure above bottom level, at least one failure in an enabled analysis child must declare a valid propagatesTo link to it. For every interface-point analysis above bottom level, at least one interface-point analysis in that child set must declare a valid usedIn link to its analysed interface point. Design.children supplies this set: enabled children contribute directly; a child with absent or disabled Analysis contributes through its own Design.children, crossing at most one bypass. Every Design edge must agree with Element.parent. At least one valid contribution covers the individual target; every child need not contribute to every target. Requirement allocation does not select contributors. A link without the required Design edges does not establish coverage, and an empty child set leaves a normal missing-coverage finding. Missing contributions are HIGH. Incoming links at bottom level, and upward links at top level, are MODERATE. Prohibited links are reported on their source failure or interface-point analysis. Missing incoming contributions stay on the receiving object and carry the ? Contributor unknown badge: the check cannot identify which child should supply the missing contribution. Missing local interface-point analysis has a known responsible Analysis and does not carry this badge.

Any authored link is still validated for correct ownership, parentage, and classifications. Severity propagation is existential: at least one target must have severity greater than or equal to the source failure. Other targets may have lower severity. Missing links and missing severity values have separate HIGH completeness findings.

The common classification policy reports excessive source classifications as HIGH on the source, and a target above all incoming contributors as INFO on the target. Analysis and InterfacePointAnalysis have no independent ASIL; failures use their referenced interface point's ASIL.

All missing required values and references are HIGH: applicable names, descriptions and ASIL, failure severity and multiplicity, and conditionally required hierarchy links. A failure requires at least one safety measure (including a safety mechanism) in mitigatedBy or at least one valid independent failure unless it is explicitly QM with severity below S10. Missing ASIL or severity does not exempt the failure. Invalid severity values above S10 retain the mitigation requirement as well as their severity-value finding.

independentFailures is a typed Failure list required for MULTIPLE_POINT at or above S10, or when severity is missing (at least one entry; a failure may list more than one independent alternative). Below S10, this list is optional regardless of ASIL. A self-reference, a failure on the same element, or a failure on any direct or indirect ancestor or descendant element is HIGH. Siblings and elements on separate branches can be independent. An invalid reference does not satisfy the S10 alternative. A nonempty list supplied for SINGLE_POINT is MODERATE. Every failure must record evaluation = FailureEvaluation.SUFFICIENT or FailureEvaluation.RESIDUAL. GAP and a missing evaluation produce HIGH on the failure. Record the engineering reasoning in argument; linking an issue does not reduce the finding's severity. The enclosing analysis's evaluation does not supply the failure's judgment, and a sufficient or residual judgment does not waive the other failure rules. Occurrence, risk, diagnostic coverage and comment remain optional. Severity.S0 and explicit ASIL.QM are valid values. Neither boundary flag waives field completeness, containment, the S10 mitigation requirement, or test verification.

A failure description must start with the complete name of the analysed element, then mention the complete name of the exact interface point referenced by its owning interface-point analysis. Whitespace is normalized; names are matched exactly. Violations of that formulation are MODERATE. Describe faulty behaviour without requiring a normative “shall”.

An element's Gradle check and IDEA inspections load the entire module and the complete content of modules directly referenced by its objects, including its parent and Design children. A bypass needs no loading exception: an authored usedIn or propagatesTo link to the grandparent selects that module as ordinary context. Bypassing the parent alone does not load the grandparent, and references originating only in context do not select more modules. If a required link is absent, its missing-link rule reports the omission without searching further ancestors. Incoming coverage still requires complete contributor content. If a required grandchild lies outside the module's direct references, the module check reports missing context; use explicit model context or the full-project check to assess that coverage. Unloaded grandchildren are not evidence of missing contributions. The root :stigCheckModel checks every module while sharing the complete project inventory as relation context. See Model-check context for the shared scope and report locations.

Check and render

./gradlew :path:to:element:stigCheckModel ./gradlew :path:to:element:stigGenerateHtml

The Analysis section of the generated model-rule catalog defines the current containment, completeness, ASIL, multiplicity, safety-measure, and propagation checks.

Ask $stig:specification

Use $stig:specification to review the Analysis viewpoint for <module path>. Follow every interface, safety-measure, and propagatesTo link; distinguish modeled propagation from implementation path evidence; report exact rule violations without editing.
23 October 2026