diff --git a/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl
index b30dedc2..ebb55b45 100644
--- a/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl
+++ b/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl
@@ -25,34 +25,15 @@
five-safes-crate:SignOffPhaseStartTime
a sh:NodeShape ;
- sh:name "SignOffPhaseStartTime" ;
-
- sh:target [
- a sh:SPARQLTarget ;
- sh:select """
- PREFIX schema:
- PREFIX shp:
- SELECT ?this
- WHERE {
- ?this schema:additionalType shp:SignOff ;
- schema:actionStatus ?status .
- FILTER(?status IN (
- "http://schema.org/ActiveActionStatus",
- "http://schema.org/CompletedActionStatus",
- "http://schema.org/FailedActionStatus"
- ))
- }
- """ ;
+ sh:description "Sign Off start time check" ;
+ sh:severity sh:Info ;
+ sh:target [
+ a five-safes-crate:ActionActiveCompFailSearch ;
+ five-safes-crate:addtype shp:SignOff ;
] ;
-
sh:property [
- a sh:PropertyShape ;
- sh:name "StartTime" ;
sh:path schema:startTime ;
sh:minCount 1 ;
sh:maxCount 1 ;
- sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ;
- sh:severity sh:Info ;
- sh:description "Sign Off object MAY have a startTime property if action is active, completed or failed. This must follow ISO-8601 syntax" ;
- sh:message "Sign Off object MAY have a startTime property if action is active, completed or failed. This must follow ISO-8601 syntax" ;
+ sh:message "Sign Off phase MAY have a startTime if action is active, completed or failed." ;
] .
diff --git a/rocrate_validator/profiles/five-safes-crate/must/11_workflow_execution_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/11_workflow_execution_phase.ttl
index 4551da6c..bf10ac56 100644
--- a/rocrate_validator/profiles/five-safes-crate/must/11_workflow_execution_phase.ttl
+++ b/rocrate_validator/profiles/five-safes-crate/must/11_workflow_execution_phase.ttl
@@ -72,7 +72,9 @@ five-safes-crate:WorkflowexecutionObjectHasCompliantEndTimeFormat
sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ;
sh:severity sh:Violation ;
sh:message "The endTime of the workflow execution object MUST follow the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ;
- ] .
+ ] ;
+
+ sh:node five-safes-crate:EndTimeStamp .
five-safes-crate:WorkflowMustHaveActionStatusWithAllowedValues
diff --git a/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl
index 2b61a259..854cd9e6 100644
--- a/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl
+++ b/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl
@@ -21,6 +21,7 @@
@prefix sh: .
@prefix validator: .
@prefix xsd: .
+@prefix shp: .
five-safes-crate:SignOffObjectActionAndName
a sh:NodeShape ;
@@ -53,7 +54,11 @@ five-safes-crate:SignOffObjectActionAndName
sh:hasValue schema:AssessAction;
sh:severity sh:Violation ;
sh:message "Sign Off phase MUST be a `schema:AssessAction`." ;
- ] .
+ ] ;
+
+ sh:node five-safes-crate:StartTimeStamp ;
+
+ sh:node five-safes-crate:EndTimeStamp .
five-safes-crate:SignOffObjectHasActionStatus
a sh:NodeShape ;
diff --git a/rocrate_validator/profiles/five-safes-crate/shape_library.ttl b/rocrate_validator/profiles/five-safes-crate/shape_library.ttl
new file mode 100644
index 00000000..6607e3bc
--- /dev/null
+++ b/rocrate_validator/profiles/five-safes-crate/shape_library.ttl
@@ -0,0 +1,99 @@
+# Copyright (c) 2025 eScience Lab, The University of Manchester
+#
+# 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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+@prefix ro: <./> .
+@prefix ro-crate: .
+@prefix five-safes-crate: .
+@prefix rdf: .
+@prefix rdfs: .
+@prefix schema: .
+@prefix sh: .
+@prefix validator: .
+@prefix xsd: .
+@prefix shp: .
+
+
+five-safes-crate:EndTimeStamp
+ a sh:NodeShape ;
+ sh:property [
+ sh:datatype xsd:string ;
+ sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ;
+ sh:description "End Time Check" ;
+ sh:path schema:endTime ;
+ sh:minCount 0 ;
+ sh:name "EndTimeStamp" ;
+ sh:message "endTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00" ;
+ sh:severity sh:Violation ;
+ ] .
+
+
+five-safes-crate:StartTimeStamp
+ a sh:NodeShape ;
+ sh:property [
+ sh:datatype xsd:string ;
+ sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ;
+ sh:description "Start Time Check" ;
+ sh:path schema:startTime ;
+ sh:minCount 0 ;
+ sh:name "StartTimeStamp" ;
+ sh:message "startTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00" ;
+ sh:severity sh:Violation ;
+ ] .
+
+
+five-safes-crate:ActionCompFailSearch
+ a sh:SPARQLTargetType ;
+ rdfs:subClassOf sh:Target ;
+ sh:parameter [
+ sh:path five-safes-crate:addtype ;
+ sh:description "Additional Type for Class" ;
+ sh:class sh:additionalType ;
+ ] ;
+ sh:select """
+ PREFIX schema:
+ PREFIX shp:
+ SELECT ?this
+ WHERE {
+ ?this schema:additionalType $addtype ;
+ schema:actionStatus ?status .
+ FILTER(?status IN (
+ "http://schema.org/CompletedActionStatus",
+ "http://schema.org/FailedActionStatus"
+ ))
+ }
+ """ .
+
+
+five-safes-crate:ActionActiveCompFailSearch
+ a sh:SPARQLTargetType ;
+ rdfs:subClassOf sh:Target ;
+ sh:parameter [
+ sh:path five-safes-crate:addtype ;
+ sh:description "Additional Type for Class" ;
+ sh:class sh:additionalType ;
+ ] ;
+ sh:select """
+ PREFIX schema:
+ PREFIX shp:
+ SELECT ?this
+ WHERE {
+ ?this schema:additionalType $addtype ;
+ schema:actionStatus ?status .
+ FILTER(?status IN (
+ "http://schema.org/ActiveActionStatus",
+ "http://schema.org/CompletedActionStatus",
+ "http://schema.org/FailedActionStatus"
+ ))
+ }
+ """ .
diff --git a/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl
index d671a0d9..30cc15fc 100644
--- a/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl
+++ b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl
@@ -22,6 +22,9 @@
@prefix xsd: .
@prefix shp: .
+<> a sh:ShapesGraph ;
+ sh:import <../shape_library.ttl> .
+
# There SHOULD be a Sign-Off Phase
five-safes-crate:SignOffPhase
@@ -147,32 +150,13 @@ five-safes-crate:SignOffPhaseProperties
five-safes-crate:SignOffPhaseEndTime
a sh:NodeShape ;
sh:description "Sign Off end time check" ;
-
- sh:target [
- a sh:SPARQLTarget ;
- sh:select """
- PREFIX schema:
- PREFIX shp:
- SELECT ?this
- WHERE {
- ?this schema:additionalType shp:SignOff ;
- schema:actionStatus ?status .
- FILTER(?status IN (
- "http://schema.org/CompletedActionStatus",
- "http://schema.org/FailedActionStatus"
- ))
- }
- """ ;
+ sh:node five-safes-crate:EndTimeStamp ;
+ sh:severity sh:Warning ;
+ sh:target [
+ a five-safes-crate:ActionCompFailSearch ;
+ five-safes-crate:addtype shp:SignOff ;
] ;
+ sh:message "Sign Off phase SHOULD have a compliant endTime if action completed or failed."
+ .
+
- sh:property [
- a sh:PropertyShape ;
- sh:name "EndTime" ;
- sh:path schema:endTime ;
- sh:minCount 1 ;
- sh:maxCount 1 ;
- sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ;
- sh:severity sh:Warning ;
- sh:description "Sign Off object SHOULD have endTime property if action completed or failed. This must follow ISO-8601 syntax" ;
- sh:message "Sign Off object SHOULD have endTime property if action completed or failed. This must follow ISO-8601 syntax" ;
- ] .
diff --git a/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py
index 7f9cd8f3..5f4fdb86 100644
--- a/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py
+++ b/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py
@@ -206,10 +206,10 @@ def test_5src_signoff_phase_no_endtime():
rocrate_path=ValidROC().five_safes_crate_result,
requirement_severity=Severity.RECOMMENDED,
expected_validation_result=False,
- expected_triggered_requirements=["SignOffPhaseEndTime"],
+ expected_triggered_requirements=["SignOffPhaseEndTime", "EndTimeStamp"],
expected_triggered_issues=[
- "Sign Off object SHOULD have endTime property if action completed or failed."
- + " This must follow ISO-8601 syntax"
+ "Sign Off phase SHOULD have a compliant endTime if action completed or failed.",
+ "endTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00"
],
profile_identifier="five-safes-crate",
rocrate_entity_mod_sparql=sparql,
@@ -242,10 +242,10 @@ def test_5src_signoff_phase_malformed_endtime():
rocrate_path=ValidROC().five_safes_crate_result,
requirement_severity=Severity.RECOMMENDED,
expected_validation_result=False,
- expected_triggered_requirements=["SignOffPhaseEndTime"],
+ expected_triggered_requirements=["SignOffPhaseEndTime", "EndTimeStamp"],
expected_triggered_issues=[
- "Sign Off object SHOULD have endTime property if action completed or failed."
- + " This must follow ISO-8601 syntax"
+ "Sign Off phase SHOULD have a compliant endTime if action completed or failed.",
+ "endTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00"
],
profile_identifier="five-safes-crate",
rocrate_entity_mod_sparql=sparql,
@@ -274,10 +274,10 @@ def test_5src_signoff_phase_no_starttime():
rocrate_path=ValidROC().five_safes_crate_result,
requirement_severity=Severity.OPTIONAL,
expected_validation_result=False,
- expected_triggered_requirements=["SignOffPhaseStartTime"],
+ expected_triggered_requirements=["SignOffPhaseStartTime", "StartTimeStamp"],
expected_triggered_issues=[
- "Sign Off object MAY have a startTime property if action is active, completed or failed."
- + " This must follow ISO-8601 syntax"
+ "Sign Off phase MAY have a compliant startTime if action is active, completed or failed.",
+ "startTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00"
],
profile_identifier="five-safes-crate",
rocrate_entity_mod_sparql=sparql,
@@ -310,10 +310,10 @@ def test_5src_signoff_phase_malformed_starttime():
rocrate_path=ValidROC().five_safes_crate_result,
requirement_severity=Severity.OPTIONAL,
expected_validation_result=False,
- expected_triggered_requirements=["SignOffPhaseStartTime"],
+ expected_triggered_requirements=["SignOffPhaseStartTime", "StartTimeStamp"],
expected_triggered_issues=[
- "Sign Off object MAY have a startTime property if action is active, completed or failed."
- + " This must follow ISO-8601 syntax"
+ "Sign Off phase MAY have a compliant startTime if action is active, completed or failed.",
+ "startTime property MUST follow ISO-8601 syntax. e.g. 2023-04-19T10:15:12+01:00"
],
profile_identifier="five-safes-crate",
rocrate_entity_mod_sparql=sparql,