From 9f0074136c951605f52bd72f97f98fc75a1f17c7 Mon Sep 17 00:00:00 2001 From: aorzelskiGH Date: Fri, 17 Apr 2026 17:07:44 +0200 Subject: [PATCH] feat(access-rules): add supplementalSemanticIds support to FieldIdentifier Align the Security Access Rules BNF and JSON Schema with the supplementalSemanticIds extensions that the API spec already uses in its modelStringPattern (IDTA-01002 FieldIdentifier). Previously, the Security grammar allowed only semanticId under $sm#, $sme#, $aasdesc#submodelDescriptors.* and $smdesc#. Access rules that want to scope permissions by supplementalSemanticIds were therefore formally invalid against the Security schema, even though the API query language supports them. Changes: - access-rules.bnf and extended to accept "supplementalSemanticIds" ( "[" [0-9]* "]" )? ( "." )? in addition to the existing semanticId forms. - aas-queries-and-access-rules-schema.json formulas-and-logical-expressions.json FieldIdentifier / FieldIdentifierAAS and FragmentFieldIdentifier patterns widened to include supplementalSemanticIds under $sm#, $sme#, $aasdesc#submodelDescriptors.*, $smdesc#, mirroring the API modelStringPattern. - new example allow-read-supplemental-semantic-id.(bnf|json) demonstrates a rule scoped by supplementalSemanticIds. Additive change; all previously valid rules stay valid. Refs: Review Finding T-05 Made-with: Cursor --- .../ROOT/partials/bnf/access-rules.bnf | 4 +-- .../allow-read-supplemental-semantic-id.bnf | 9 +++++ .../allow-read-supplemental-semantic-id.json | 34 +++++++++++++++++++ .../aas-queries-and-access-rules-schema.json | 4 +-- .../formulas-and-logical-expressions.json | 2 +- 5 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.bnf create mode 100644 documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.json diff --git a/documentation/IDTA-01004/modules/ROOT/partials/bnf/access-rules.bnf b/documentation/IDTA-01004/modules/ROOT/partials/bnf/access-rules.bnf index 9c858a0..17f56a0 100644 --- a/documentation/IDTA-01004/modules/ROOT/partials/bnf/access-rules.bnf +++ b/documentation/IDTA-01004/modules/ROOT/partials/bnf/access-rules.bnf @@ -217,7 +217,7 @@ ::= "interface" | "protocolinformation.href" ::= ( "type" | "keys" ( "[" ( [0-9]* ) "]" ) ( ".type" | ".value" ) ) - ::= ( "semanticId" | "semanticId." ) + ::= ( "semanticId" | "semanticId." | "supplementalSemanticIds" ( "[" ( [0-9]* ) "]" )? ( "." )? ) ::= ( "specificAssetIds" ( "[" ( [0-9]* ) "]" ) ( ".name" | ".value" | ".externalSubjectId" | ".externalSubjectId." ) ) @@ -234,7 +234,7 @@ ::= ( | "idShort" | ) ::= "endpoints" ( "[" ( [0-9]* ) "]" ) - ::= "semanticId" | "semanticId." + ::= "semanticId" | "semanticId." | "supplementalSemanticIds" ( "[" ( [0-9]* ) "]" )? ( "." )? ::= "keys[" ( [0-9]* ) "]" diff --git a/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.bnf b/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.bnf new file mode 100644 index 0000000..ab576a1 --- /dev/null +++ b/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.bnf @@ -0,0 +1,9 @@ +ACCESSRULE: + ATTRIBUTES: + GLOBAL(ANONYMOUS) + RIGHTS: READ + ACCESS: ALLOW + OBJECTS: + ROUTE "*" + FORMULA: + $sm#supplementalSemanticIds[].keys[0].value $eq "https://example.com/ids/IEC61360" diff --git a/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.json b/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.json new file mode 100644 index 0000000..90d775c --- /dev/null +++ b/documentation/IDTA-01004/modules/ROOT/partials/examples/allow-read-supplemental-semantic-id.json @@ -0,0 +1,34 @@ +{ + "AllAccessPermissionRules": { + "rules": [ + { + "ACL": { + "ATTRIBUTES": [ + { + "GLOBAL": "ANONYMOUS" + } + ], + "RIGHTS": [ + "READ" + ], + "ACCESS": "ALLOW" + }, + "OBJECTS": [ + { + "ROUTE": "*" + } + ], + "FORMULA": { + "$eq": [ + { + "$field": "$sm#supplementalSemanticIds[].keys[0].value" + }, + { + "$strVal": "https://example.com/ids/IEC61360" + } + ] + } + } + ] + } +} diff --git a/documentation/IDTA-01004/modules/ROOT/partials/json/aas-queries-and-access-rules-schema.json b/documentation/IDTA-01004/modules/ROOT/partials/json/aas-queries-and-access-rules-schema.json index 3a15b94..2c799af 100644 --- a/documentation/IDTA-01004/modules/ROOT/partials/json/aas-queries-and-access-rules-schema.json +++ b/documentation/IDTA-01004/modules/ROOT/partials/json/aas-queries-and-access-rules-schema.json @@ -10,11 +10,11 @@ }, "FieldIdentifier": { "type": "string", - "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|submodels\\[[0-9]*\\]\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))|\\$sm#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|value|valueType|language)|\\$cd#(?:idShort|id)|\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))|\\$smdesc#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))$" + "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|submodels\\[[0-9]*\\]\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))|\\$sm#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|value|valueType|language)|\\$cd#(?:idShort|id)|\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))|\\$smdesc#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))$" }, "FragmentFieldIdentifier": { "type": "string", - "pattern": "^(?:\\$aas#(?:idShort|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\](?:\\.externalSubjectId(?:\\.keys\\[[0-9]*\\])?)?|submodels\\[[0-9]*\\](?:\\.keys\\[[0-9]*\\])?)|\\$sm#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?(?:#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|idShort|value|valueType|language))?|\\$cd#idShort|\\$aasdesc#(?:idShort|description|displayName|extension|administration|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\](?:\\.externalSubjectId(?:\\.keys\\[[0-9]*\\])?)?|endpoints\\[[0-9]*\\]|submodelDescriptors\\[[0-9]*\\](?:\\.(?:semanticId(?:\\.keys\\[[0-9]*\\])?|idShort|endpoints\\[[0-9]*\\]))?)|\\$smdesc#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|idShort|endpoints\\[[0-9]*\\]))$" + "pattern": "^(?:\\$aas#(?:idShort|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\](?:\\.externalSubjectId(?:\\.keys\\[[0-9]*\\])?)?|submodels\\[[0-9]*\\](?:\\.keys\\[[0-9]*\\])?)|\\$sm#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.keys\\[[0-9]*\\])?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?(?:#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.keys\\[[0-9]*\\])?|idShort|value|valueType|language))?|\\$cd#idShort|\\$aasdesc#(?:idShort|description|displayName|extension|administration|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\](?:\\.externalSubjectId(?:\\.keys\\[[0-9]*\\])?)?|endpoints\\[[0-9]*\\]|submodelDescriptors\\[[0-9]*\\](?:\\.(?:semanticId(?:\\.keys\\[[0-9]*\\])?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.keys\\[[0-9]*\\])?|idShort|endpoints\\[[0-9]*\\]))?)|\\$smdesc#(?:semanticId(?:\\.keys\\[[0-9]*\\])?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.keys\\[[0-9]*\\])?|idShort|endpoints\\[[0-9]*\\]))$" }, "hexLiteralPattern": { "type": "string", diff --git a/documentation/IDTA-01004/modules/ROOT/partials/json/formulas-and-logical-expressions.json b/documentation/IDTA-01004/modules/ROOT/partials/json/formulas-and-logical-expressions.json index c9edd68..7130f41 100644 --- a/documentation/IDTA-01004/modules/ROOT/partials/json/formulas-and-logical-expressions.json +++ b/documentation/IDTA-01004/modules/ROOT/partials/json/formulas-and-logical-expressions.json @@ -6,7 +6,7 @@ }, "FieldIdentifierAAS": { "type": "string", - "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|submodels\\[[0-9]*\\]\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))|\\$sm#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|value|valueType|language)|\\$cd#(?:idShort|id)|\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))|\\$smdesc#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))$" + "pattern": "^(?:\\$aas#(?:idShort|id|assetInformation\\.assetKind|assetInformation\\.assetType|assetInformation\\.globalAssetId|assetInformation\\.specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|submodels\\[[0-9]*\\]\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))|\\$sm#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id)|\\$sme(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*(?:\\.[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?(?:\\[[0-9]*\\])*)*)?#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|value|valueType|language)|\\$cd#(?:idShort|id)|\\$aasdesc#(?:idShort|id|assetKind|assetType|globalAssetId|specificAssetIds\\[[0-9]*\\]\\.(?:name|value|externalSubjectId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?)|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)|submodelDescriptors\\[[0-9]*\\]\\.(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))|\\$smdesc#(?:semanticId(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|supplementalSemanticIds(?:\\[[0-9]*\\])?(?:\\.(?:type|keys\\[[0-9]*\\]\\.(?:type|value)))?|idShort|id|endpoints\\[[0-9]*\\]\\.(?:interface|protocolinformation\\.href)))$" }, "hexLiteralPattern": { "type": "string",