Metanorma machine-readable requirements ("MRR") requirements model scheme
Metanorma machine-readable requirements ("MRR") is a generic requirements model scheme developed according to the needs of NIST and ITU with a focus on machine-readability.
This document describes the models provided by the MRR scheme and their usage.
The major benefit of MRR, in comparison with other requirements model schemes, is its focus on making requirements machine-readable and executable.
Many standards and specifications today are meant for encoding data and behavioral requirements intended for machines or software. Instead of needing human intervention or re-interpretation of these requirements for machines, it is possible to streamline the semantics between the specification of requirements and the machine usage of such requirements.
MRR was originally announced at the ISO/TMB/SAG_MRS ("Special Advisory Group for Machine-Readable Standards") in 2019, and placed into production the same year.
|The Multi-Modal Modelling Language ("MMEL"), a core component of the BSI SMART program supported by the Ministry of Defense, UK, is implemented as a superset of MRR.|
Use cases supported by MRR include:
representation of a requirements collection or a requirements graph of a coherent set of compliance criteria;
automated validation of the consistency of a set of requirements;
automated execution of automated processing steps as specified by as requirements;
automated compliance checks against machine-readable verification tests.
The architecture of MRR is described in the MRR model diagram.
Two core classes:
Three models that can be instantiated:
The three instantiable models provide the basis for encoding machine-readable requirements. The only difference between these three models is the obligation, which binds the subject to a different strength in terms of compliance.
One aspect that MRR differs from other requirements model schemes is that it relies on "components" to differentiate roles of provisions. (see Components for details). Components may be targeted towards human- or machine-readability.
The method of encoding an MRR model follows the general syntax described in requirements.
The encoding syntax is as follows, where the block definition describes the type of the model.
[permission] ==== This is the permission statement. ====
|Additional examples of MRR encodings are available at metanorma-mrr-samples.|
When using MRR within other documents that, by default, uses another
requirements model scheme, it is necessary specify the instance with the
[requirement,model=mrr] ==== This is an MRR requirement ====
An MRR model instance is encoded with one of these block types:
All instantiable models in MRR share the same set of attributes.
The following attributes are supported:
(optional) The requirement model scheme that applies to the instance. (default:
(optional) The model of the instance, typically not necessary given the type has been specified at the block level (e.g.
The identifier assigned to an instance. Identifiers can be simple strings, and are often entered as URIs or URNs. If present, it will be rendered in final output. [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v2.2.0]Note
identifierwas previously called
May be used to give an arbitrary number of key-value pairs of tags describing the instance. Key and value are separated by a colon, multiple values are delimited by comma, and key-value pairs are delimited by semicolon. Both key and value are expected to be tokens containing no punctuation.
(optional) Modality of the instance, as in the strength to which it pertains to compliance. Can contain one or more of
recommendation, comma-delimited. Using this attribute will override the obligation of the requirement.
May be used to reference the label of a requirement or definition that is imported or presupposed by this requirement. Can contain multiple semicolon-delimited identifiers. [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v1.3.14].
Multiple instances of
inheritcan also be expressed with the
inheritcommand, which can contain markup including cross-references [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v1.3.21].
Any attributes that are not included in the list of requirement attributes above are treated as "classification tags". [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v2.2.0]
Components are a core part of how to represent content within MRR instances.
The recognized component types are:
measurement-target(for quantitative requirements)
verification(verification steps for the requirement)
Behavioral interfaces (code stubs):
component[added in https://github.com/metanorma/metanorma-standoc/releases/tag/v1.10.4]
Components of a requirement can be encoded in order to make it machine-readable in Metanorma normative outputs, although this is not expected to be reflected in renderings.
Components are encoded within an MRR instance using named blocks. Each block needs to be named with the kind of component it contains as a role attribute.
A component block is encoded using the following mechanisms:
open blocks, which are marked up with a succession of two or more hyphens (
---…), [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v1.10.6]
example blocks, which are marked up with a succession of four or more equals signs (
Any text not wrapped in a named block is considered to be part of the description of the outermost MRR instance (e.g. a requirement).
[requirement] ==== [specification] -- This is a formal specification -- [measurement-target] ===== This is a measurement target ===== [verification] -- This is a verification step -- [import] -- This is a code stub -- ====
A specification is a formal statement that describes the object of the requirement.
The specification component is identified by the
[requirement] ==== [statement] -- An identifier shall be unique. -- ====
Specifications can be described with machine-readable content. These components
can be specified with the classification of
In the following example, an OpenAPI specification is used directly to specify requirements on the subject.
[requirement] ==== [%metadata] identifier:: /openapi/3.0/ classification:: type:openapi [specification] -- [source,yaml] ---- include::openapi.yaml ---- -- ====
A measurement target indicates the target that a measurement is to be taken from, in order to express quantitative requirements.
The measurement target component is identified by the
[requirement] ==== [measurement-target] -- The value for stem:[alpha] shall be within 0.1 and 0.3. -- ====
A verification component provides verification steps for the MRR instance. This is typically a set of sequential steps that verifies compliance towards the instance.
The measurement target component is identified by the
with contents encoded as an ordered list.
[requirement] ==== [%metadata] identifier:: /ss/584/2015/level/1 subject:: The Cloud Service Provider's management and board of directors classification:: type:text [specification] -- . Managing information security risks related to people, process, technology and governance. . Oversight of the effective implementation of the technology controls. . Oversight of risk management practices. -- [verification] -- . Determine that the responsibilities of management and board of directors in managing and overseeing information security risks are documented and communicated. . Inspect documents such as meeting minutes and committee charter to identify the participants involved in the meeting or committee, their respective job functions and the reporting relationship. . Determine whether the management and board of directors meet regularly, at an appropriate and monitored frequency. . Determine whether the information security function is headed by a Chief Information Security Officer (CISO) or similar function. -- ====
A behavioral interface specifies compliance conditions of the target subject, by specifying the desired behavior of the subject.
A behavioral interface can be specified with a mix of human-readable and machine-readable content.
The behavioral interface component is specified with the
Depending on the language used within the
import block, different attributes
|The term "interface" originates from its meaning from programming languages, and can be considered a way of entering "acceptance tests".|
.Generic Structure for Permutation Testing [requirement] ==== [%metadata] identifier:: /iid-testing/permutation-test/ [description] -- Input:: stem:[S = (s_1, ... s_L)] Output:: Decision on the IID assumption -- [verification] -- . For each test stem:[i] .. Assign the counters stem:[C_(i, 0)] and stem:[C_(i, 1)] to zero. .. Calculate the test statistic stem:[T_(i)] on stem:[S]. . For stem:[j = 1] to 10 000 .. Permute stem:[S] using the Fisher-Yates shuffle algorithm. .. For each test stem:[i] ... Calculate the test statistic stem:[T] on the permuted data. ... If (stem:[T > T_(i)]), increment stem:[C_(i, 0)]. If (stem:[T = T_(i)]), increment stem:[C_(i, 1)]. . If ( (stem:[C_(i, 0) + C_(i, 1) <= 5]) or (stem:[C_(i, 0) >= 9995]) ) for any stem:[i], reject the IID assumption; else, assume that the noise source outputs are IID. -- [import, type="pseudo-fortress", run="DecideIID"] ---- import FisherYatesShuffle, TestStatistic DecideIID(S: ZZ, L: RR) : Boolean = for i <- 1 : L do C[i, 0] <- 0, C[i, 1] <- 0 T[i] <- TestStatistic(S) end for j <- 1 : 10000 do S' <- FisherYatesShuffle(S) for i <- 1: L do T <- TestStatistic(S') if T' > T'[i] C[i, 0] <- C[i, 0] + 1 end if T' == T[i] C[i, 1] <- C[i, 1] + 1 end end end for i <- 1 : L do if (C[i, 0] + C[i, 1] <= 5) or (C[i, 0] >= 9995) return false end end return true ---- ====
A custom component (not among the defined components allowed) can be encoded
class attribute, to specify the particular kind of component. If no
such attribute is given, the default value is the undifferentiated component
component) [added in https://github.com/metanorma/metanorma-standoc/releases/tag/v1.10.4].
[requirement] ==== [component,class=conditions] -- The following conditions need to be fulfilled in this requirement... -- ====
Any component may include or consist of machine-readable code.
Components can be specified with a "type" if they are intended to be machine-readable. The "type" refers to the conventions or computer frameworks that they follow.
They are given by setting the
type attribute on the component block:
[requirement] ==== [%metadata] identifier:: requirement A This is some descriptive text. [specification,type=ABNF] -- [source,abnf] ---- status = ( "draft" / "cancelled" ) / stage stage = "stage-" stagecode ["." iteration] stagecode = DIGIT DIGIT "." DIGIT DIGIT iteration = "v" DIGITS ---- -- This is some more descriptive text. ====
Source code as specification
Such content is to be provided within a
[source] block, which is expected to
contain an attribute giving the computer language the block is expressed in.
|The notion of "language" may be expanded to include a particular computer framework that the code is to be run under.|
It is also possible specify “source code” that is meant to be human readable,
The language of a source code block is likely to be distinct from the type of named block it is contained in.
[requirement] ==== [%metadata] identifier:: Requirement A This is some descriptive text. [verification,type=heuristic] -- [source,ruby] ---- instances.each do |i| warn "uh-oh" if i > 5 end ---- -- ====
Machine-readable content as alternative representation
By default, all components and descriptions will be included in final output.
Often, though not always, components can contain machine-readable code which is not intended to be included in the output, but is supplemental to the human-readable description.
That is signalled through the options attribute
exclude on the named block.
[recommendation] ==== [%metadata] identifier:: /ogc/recommendation/wfs/2 subject:: user I recommend _this_. [specification,type="tabular"] -- This is the object of the recommendation: |=== |Object |Value |Mission | Accomplished |=== -- As for the measurement targets, [measurement-target] -- The measurement target shall be measured as: [stem] ++++ r/1 = 0 ++++ -- [verification,type="comprehensive"] -- The following code will be run for verification: [source,CoreRoot] ---- CoreRoot(success): HttpResponse if (success) recommendation(label: success-response) end ---- -- [import%exclude] -- [source,CoreRoot] ---- success-response() ---- -- ====
Nested requirements can be encoded with a combination of internal blocks.
MRR requirements can be nested by adding one or more delimiter symbols than its containing block.
[permission] ==== The permission statement surrounded by 4 delimiter symbols. [example] ===== An example within the permission surrounded by 5 delimiter symbols. ===== [permission] ===== A sub-permission surrounded by 5 delimiter symbols. ===== [requirement] ===== A requirement if the permission is adopted. ===== ====
|Nested requirements are marked up just like nested examples.|
[requirement] ==== [%metadata] identifier:: requirement A [requirement] ===== [%metadata] identifier:: requirement A1 [specification] -- This is a formal specification. -- ===== [requirement] ===== [%metadata] identifier:: requirement A2 [measurement-target] -- This is a measurement target. -- ===== ====