diff --git "a/qq\033OA" "b/qq\033OA"
new file mode 100644
index 00000000..f89407e2
--- /dev/null
+++ "b/qq\033OA"
@@ -0,0 +1,164 @@
+[37m [0m[37m [0m[37m [0m
+[37m [0m[1;37mThe following requirements have not meet: [0m[37m [0m[37m [0m
+
+ [1m[[0mprofile: [1;35mFive Safes RO-Crate [0m[1;35m0.4[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m five-safes-crate-[0m[1;4;36m0.[0m[1;4;36m4_5 [0m[1;4;36m][0m[1;4;36m: Downloaded Workflow[0m[37m [0m[37m [0m
+
+ Profile Requirement Downloaded Workflow
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;31m[[0m[1;31m five-safes-crate-[0m[1;31m0.[0m[1;31m4_5.[0m[1;31m0[0m[1;31m [0m[1;31m][0m[1;37m [0m[1;35mDownloaded Workflow[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m"[4;32mfile:///home/ettore/Work/rocrate-validator/tests/data/crates/valid/five-safes-crate-result/workflow/289/[0m" on [1;36m<[0m[1;36m.[0m[36m/workflow/289/[0m[36m>[0m[1;39m][0m[39m: DownloadedWorkflow --> `distribution` MUST be [0m
+ [39mreferesed by `DownloadAction` --[0m[1m>[0m `object`.
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_22 [0m[1;4;36m][0m[1;4;36m: RO-Crate Root Data Entity RECOMMENDED properties[0m[37m [0m[37m [0m
+
+ The Root Data Entity SHOULD have the properties [1;36;40mname[0m, [1;36;40mdescription[0m and [1;36;40mlicense[0m defined as described in the RO-Crate specification [4;34mhttps://www.researchobject.org/ro-crate/1.1/root-data-entity.html[0m
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_22.[0m[1;38;5;214m1[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mRoot Data Entity: `licence` SHOULD link to a Contextual Entity[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the Root Data Entity includes a [1;36;40mlicense[0m property that links to a Contextual Entity with type [1;36;40mschema_org:CreativeWork[0m to describe the license.
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m of [4;33mhttp://schema.org/[0m[4;33mlicense[0m[4;94m=[0m[32m"[0m[32mhttp[0m[32m://spdx.org/licenses/CC-BY-4.0[0m[32m"[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[1;36m>[0m[1m][0m: The Root Data Entity SHOULD have a link to a Contextual Entity representing the schema_org:license
+ type
+
+
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_22.[0m[1;38;5;214m2[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mRoot Data Entity: `author` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the Root Data Entity includes a [1;36;40mauthor[0m property (as specified by schema.org) to provide information about its author.
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[1;36m>[0m[1m][0m: The Root Data Entity SHOULD have a link to a Contextual Entity representing the `author` of the RO-Crate
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_25 [0m[1;4;36m][0m[1;4;36m: Directory Data Entity: RECOMMENDED value restriction[0m[37m [0m[37m [0m
+
+ A Directory Data Entity SHOULD end with [1;36;40m/[0m
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_25.[0m[1;38;5;214m1[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mDirectory Data Entity: RECOMMENDED value restriction[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the Directory Data Entity ends with [1;36;40m/[0m
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m of [33mna464348be5bf4fa48130a7e5297e81c6b7[0m=[32m"[0m[32mhttps[0m[32m://workflowhub.eu/workflows/289?[0m[32mversion[0m[32m=[0m[32m1[0m[32m"[0m on [1;36m<[0m[4;36mhttps:[0m[4;36m//github.com/crs4/rocrate-validator/profiles/ro-crate/Directory[0m[1;36m>[0m[1m][0m: Every Data
+ Entity Directory URI SHOULD end with `[35m/[0m`
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_26 [0m[1;4;36m][0m[1;4;36m: File Data Entity: RECOMMENDED properties[0m[37m [0m[37m [0m
+
+ A [1;36;40mFile[0m Data Entity SHOULD have detailed descriptions encodings through the [1;36;40mencodingFormat[0m property
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_26.[0m[1;38;5;214m1[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mFile Data Entity: RECOMMENDED `encodingFormat` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the File Data Entity has a detailed description of encodings through the [1;36;40mencodingFormat[0m property. The [1;36;40mencodingFormat[0m property SHOULD be a PRONOM identifier (e.g.,
+ application/pdf) or, to add more detail, SHOULD be linked using a [1;36;40mPRONOM[0m to a [1;36;40mContextual Entity[0m of type [1;36;40mWebSite[0m (see [4;34mAdding detailed descriptions of encodings[0m).
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: Missing or invalid `encodingFormat` linked to the `File Data Entity`
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_27 [0m[1;4;36m][0m[1;4;36m: Web-based Data Entity: RECOMMENDED resource availability[0m[37m [0m[37m [0m
+
+ Web-based Data Entity instances SHOULD be available at the URIs specified in the [1;36;40m@id[0m property of the Web-based Data Entity.
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_27.[0m[1;38;5;214m1[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mWeb-based Data Entity: resource availability[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the Web-based Data Entity is directly downloadable by a simple retrieval (e.g. HTTP GET) permitting redirection and HTTP/HTTPS URIs
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m[1m][0m: Web-based Data Entity [4;94mhttps://workflowhub.eu/workflows/289?[0m[4;94mversion[0m[4;94m=[0m[4;94m1[0m is not available
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_30 [0m[1;4;36m][0m[1;4;36m: Organization: RECOMMENDED properties[0m[37m [0m[37m [0m
+
+ The recommended properties for an [1;36;40mOrganization[0m are [1;36;40mname[0m and [1;36;40murl[0m.
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;38;5;214m[[0m[1;38;5;214m ro-crate-[0m[1;38;5;214m1.[0m[1;38;5;214m1_30.[0m[1;38;5;214m2[0m[1;38;5;214m [0m[1;38;5;214m][0m[1;37m [0m[1;35mOrganization: RECOMMENDED url property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the [1;36;40morganization[0m has a URL.
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[4;36mhttps:[0m[4;36m//ror.org/027m9bs27[0m[1;36m>[0m[1m][0m: The organization SHOULD have a URL.
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[4;36mhttps:[0m[4;36m//ror.org/01ee9ar58[0m[1;36m>[0m[1m][0m: The organization SHOULD have a URL.
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[4;36mhttps:[0m[4;36m//tre72.example.com/[0m[1;36m>[0m[1m][0m: The organization SHOULD have a URL.
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_31 [0m[1;4;36m][0m[1;4;36m: Directory Data Entity: OPTIONAL `distribution` property[0m[37m [0m[37m [0m
+
+ A Directory Data Entity MAY have a [1;36;40mdistribution[0m property to denote the distribution of the files within the directory
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_31.[0m[1;33m1[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mDirectory Data Entity: optional `distribution` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the Directory Data Entity has a [1;36;40mdistribution[0m property
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: The Directory Data Entity MAY have a `distribution` property to denote the distribution of the files within the directory
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/outputs/[0m[36mqa.csv[0m[1;36m>[0m[1m][0m: The Directory Data Entity MAY have a `distribution` property to denote the distribution of the files within the directory
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_32 [0m[1;4;36m][0m[1;4;36m: File Data Entity with web presence: OPTIONAL properties[0m[37m [0m[37m [0m
+
+ A File Data Entity which have a corresponding web presence, for instance a landing page that describes the file, including persistence identifiers (e.g. DOI), resolving to an intermediate HTML page
+ instead of the downloadable file directly. These can included for File Data Entities as additional metadata by using the properties: [1;36;40mìdentifier[0m, [1;36;40murl[0m, [1;36;40msubjectOf[0mand [1;36;40mmainEntityOfPage[0m
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_32.[0m[1;33m1[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mFile Data Entity: optional formal `identifier` [0m[1;35m([0m[1;35me.g. DOI[0m[1;35m)[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the File Data Entity has a formal identifier string such as a DOI
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: The File Data Entity MAY have a formal identifier specified through an `identifier` property
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/outputs/[0m[36mqa.csv[0m[1;36m>[0m[1m][0m: The File Data Entity MAY have a formal identifier specified through an `identifier` property
+
+
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_32.[0m[1;33m2[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mFile Data Entity: optional `url` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the File Data Entity has an optional [1;36;40mdownload[0m link
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: The File Data Entity MAY use a `url` property to denote a `download` link
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/outputs/[0m[36mqa.csv[0m[1;36m>[0m[1m][0m: The File Data Entity MAY use a `url` property to denote a `download` link
+
+
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_32.[0m[1;33m3[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mFile Data Entity: optional `subjectOf` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the File Data Entity includes a [1;36;40msubjectOf[0m property to link [1;36;40mCreativeWork[0m instances that mention it.
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: The File Data Entity MAY include a `subjectOf` property to link `CreativeWork` instances that mention it.
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/outputs/[0m[36mqa.csv[0m[1;36m>[0m[1m][0m: The File Data Entity MAY include a `subjectOf` property to link `CreativeWork` instances that mention it.
+
+
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_32.[0m[1;33m4[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mFile Data Entity: optional `mainEntityOfPage` property[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the File Data Entity has a [1;36;40mmainEntityOfPage[0m property
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[36minput1.txt[0m[1;36m>[0m[1m][0m: The File Data Entity MAY have a `mainEntityOfPage` property
+ - [1m[[0m[31mViolation[0m on [1;36m<[0m[1;36m.[0m[36m/outputs/[0m[36mqa.csv[0m[1;36m>[0m[1m][0m: The File Data Entity MAY have a `mainEntityOfPage` property
+
+
+
+ [1m[[0mprofile: [1;35mRO-Crate Metadata Specification [0m[1;35m1.1[0m[1m][0m
+[37m [0m[1;4;36m[[0m[1;4;36m ro-crate-[0m[1;4;36m1.[0m[1;4;36m1_34 [0m[1;4;36m][0m[1;4;36m: Root Data Entity: optional properties[0m[37m [0m[37m [0m
+
+ Define the optional properties for the Root Data Entity (e.g., license)
+
+[1;37m [0m[1;4;37m Failed checks [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;37m [0m[1;37m [0m
+[1;37m [0m[1;33m[[0m[1;33m ro-crate-[0m[1;33m1.[0m[1;33m1_34.[0m[1;33m1[0m[1;33m [0m[1;33m][0m[1;37m [0m[1;35mLicense[0m[1;37m:[0m[1;37m [0m[1;37m [0m
+ Check if the RO-Crate has a license property with a URI or a textual description
+[1;37m [0m[1;4;37m Detected issues [0m[1;37m [0m[1;37m [0m
+ - [1m[[0m[31mViolation[0m of [4;33mhttp://schema.org/[0m[4;33mlicense[0m[4;94m=[0m[32m"[0m[32mhttp[0m[32m://spdx.org/licenses/CC-BY-4.0[0m[32m"[0m on [1;36m<[0m[1;36m.[0m[36m/[0m[1;36m>[0m[1m][0m: MAY have a URI [1m([0meg for Creative Commons or Open Source licenses[1m)[0m.
+ MAY, if necessary be a textual description of how the RO-Crate may be used.
+
+
diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl
new file mode 100644
index 00000000..6562af2a
--- /dev/null
+++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl
@@ -0,0 +1,56 @@
+# 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 schema: .
+@prefix purl: .
+@prefix sh: .
+@prefix validator: .
+@prefix xsd: .
+
+
+five-safes-crate:DownloadActionMayHaveStartTimeIfBegun
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "" ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+ SELECT ?this
+ WHERE {
+ ?this rdf:type schema:DownloadAction ;
+ schema:actionStatus ?status .
+ FILTER(?status IN (
+ "http://schema.org/CompletedActionStatus",
+ "http://schema.org/FailedActionStatus",
+ "http://schema.org/ActiveActionStatus"
+ ))
+ }
+ """ ;
+ ] ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "StartTime" ;
+ sh:path schema:startTime ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:severity sh:Info ;
+ sh:message "`DownloadAction` MAY have the `startTime` property if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ;
+ ] .
diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl
new file mode 100644
index 00000000..2355bbb2
--- /dev/null
+++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl
@@ -0,0 +1,190 @@
+# 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 schema: .
+@prefix purl: .
+@prefix sh: .
+@prefix validator: .
+@prefix xsd: .
+
+
+five-safes-crate:DownloadActionObjectMUSTHavesDescriptiveName
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:targetClass schema:DownloadAction ;
+ sh:description "" ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "name" ;
+ sh:description "DownloadAction MUST have a human readable name string of at least 10 characters." ;
+ sh:path schema:name ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:datatype xsd:string ;
+ sh:minLength 10 ;
+ sh:severity sh:Violation ;
+ sh:message "DownloadAction MUST have a human readable name string of at least 10 characters." ;
+ ] .
+
+five-safes-crate:DownloadActionStartTimeMUSTFollowISOStandard
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "" ;
+ sh:targetClass schema:DownloadAction ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "StartTime" ;
+ sh:minCount 0;
+ sh:path schema:startTime ;
+ 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 "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ;
+ ] .
+
+
+five-safes-crate:DownloadActionEndTimeMUSTFollowISOStandard
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "" ;
+ sh:targetClass schema:DownloadAction ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "EndTime" ;
+ sh:minCount 0;
+ sh:path schema:endTime ;
+ 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 "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ;
+ ] .
+
+
+five-safes-crate:WorkflowSameAsAndRootDataEntityMainEntityMUSTBeTheSame
+ a sh:NodeShape ;
+ sh:name "Downloaded Workflow" ;
+ sh:description "" ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT ?this
+ WHERE {
+ ?this rdf:type schema:Dataset .
+ ?s rdf:type schema:DownloadAction ;
+ schema:result ?this .
+ }
+ """ ;
+ ];
+
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT $this
+ WHERE {
+ FILTER NOT EXISTS {
+ $this schema:sameAs ?o .
+ ?s schema:mainEntity ?o .
+ # ?o rdf:type schema:Dataset .
+ }
+ }
+ """ ;
+ sh:severity sh:Violation ;
+ sh:description "The property `sameAs` of the entity representing the downloaded workflow MUST point to the same entity as `RootDataEntity` --> `mainEntity`." ;
+ sh:message "The property `sameAs` of the entity representing the downloaded workflow MUST point to the same entity as `RootDataEntity` --> `mainEntity`." ;
+ ] .
+
+
+five-safes-crate:DownloadedWorkflowDistributionAndDownloadActionObjectMUSTBeTheSame
+ a sh:NodeShape ;
+ sh:name "Downloaded Workflow" ;
+ sh:description "" ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT ?this
+ WHERE {
+ ?this rdf:type schema:Dataset .
+ ?s rdf:type schema:DownloadAction ;
+ schema:result ?this .
+ }
+ """ ;
+ ];
+
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:name "" ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT $this
+ WHERE {
+ ?action rdf:type schema:DownloadAction .
+ FILTER NOT EXISTS {
+ $this schema:distribution ?url .
+ ?action schema:object ?url .
+ }
+ }
+ """ ;
+ sh:severity sh:Violation ;
+ sh:message "DownloadedWorkflow --> `distribution` MUST reference the same entity as `DownloadAction` --> `object`." ;
+ ] .
+
+
+five-safes-crate:DownloadActionActionStatusMUSTHaveAllowedValues
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "" ;
+
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT ?this
+ WHERE {
+ ?this rdf:type schema:DownloadAction ;
+ schema:actionStatus ?status .
+ }
+ """ ;
+ ] ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "ActionStatus" ;
+ sh:path schema:actionStatus ;
+ sh:in (
+ "http://schema.org/PotentialActionStatus"
+ "http://schema.org/ActiveActionStatus"
+ "http://schema.org/CompletedActionStatus"
+ "http://schema.org/FailedActionStatus"
+ ) ;
+ sh:severity sh:Violation ;
+ sh:message "The value of actionStatus MUST be one of the allowed values: PotentialActionStatus; ActiveActionStatus; CompletedActionStatus; FailedActionStatus." ;
+ ] .
diff --git a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl
new file mode 100644
index 00000000..71aff2fb
--- /dev/null
+++ b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl
@@ -0,0 +1,161 @@
+# 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 schema: .
+@prefix purl: .
+@prefix sh: .
+@prefix validator: .
+@prefix xsd: .
+
+
+five-safes-crate:DownloadActionEntitySHOULDExist
+ a sh:NodeShape ;
+ sh:name "RootDataEntity" ;
+ sh:description "" ;
+ sh:targetClass ro-crate:RootDataEntity ;
+
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:name "" ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT $this
+ WHERE {
+ FILTER NOT EXISTS {
+ ?s rdf:type schema:DownloadAction .
+ }
+ }
+ """ ;
+ sh:severity sh:Warning ;
+ sh:message "An entity typed DownloadAction SHOULD exist." ;
+ ] .
+
+
+
+five-safes-crate:RootDataEntitySHOULDMentionDownloadActionIfPresent
+ a sh:NodeShape ;
+ sh:name "RootDataEntity" ;
+ sh:description "" ;
+ sh:targetClass ro-crate:RootDataEntity ;
+
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:name "" ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT $this ?da
+ WHERE {
+ ?da rdf:type schema:DownloadAction .
+ FILTER NOT EXISTS {
+ $this schema:mentions ?da .
+ }
+ }
+ """ ;
+ sh:severity sh:Warning ;
+ sh:message "RootDataEntity SHOULD mention DownloadAction if this exists." ;
+ ] .
+
+
+five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "" ;
+ sh:target [
+ a sh:SPARQLTarget ;
+ sh:select """
+ PREFIX schema:
+ PREFIX rdf:
+
+ SELECT ?this
+ WHERE {
+ ?this rdf:type schema:DownloadAction ;
+ schema:actionStatus ?status .
+ FILTER(?status IN (
+ "http://schema.org/CompletedActionStatus",
+ "http://schema.org/FailedActionStatus"
+ ))
+ }
+ """ ;
+ ] ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "EndTime" ;
+ sh:path schema:endTime ;
+ sh:minCount 1 ;
+ sh:maxCount 1 ;
+ sh:severity sh:Warning ;
+ sh:message "`DownloadAction` SHOULD have the `endTime` property if `actionStatus` is either CompletedActionStatus or FailedActionStatus." ;
+ ] .
+
+
+five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionResult
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:description "Validates that DownloadAction result references an existing entity" ;
+ sh:targetClass schema:DownloadAction ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "Result" ;
+ sh:description "The result property must reference an existing entity in the RO-Crate" ;
+ sh:path schema:result ;
+ sh:minCount 1 ;
+ sh:nodeKind sh:IRI ;
+
+ sh:sparql [
+ a sh:SPARQLConstraint ;
+ sh:select """
+ PREFIX rdf:
+ PREFIX schema:
+
+ SELECT $this $value
+ WHERE {
+ $this schema:result $value .
+
+ # Entity must have BOTH type AND name (proper definition)
+ FILTER NOT EXISTS {
+ $value rdf:type schema:Dataset .
+ }
+ }
+ """ ;
+ sh:severity sh:Warning ;
+ sh:message "The entity represented the downloaded workflow is not properly defined in the RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." ;
+ ] ;
+ ] .
+
+
+five-safes-crate:DownloadActionShouldHaveActionStatus
+ a sh:NodeShape ;
+ sh:name "DownloadAction" ;
+ sh:targetClass schema:DownloadAction ;
+ sh:description "" ;
+
+ sh:property [
+ a sh:PropertyShape ;
+ sh:name "ActionStatus" ;
+ sh:path schema:actionStatus ;
+ sh:minCount 1 ;
+ sh:severity sh:Warning ;
+ sh:message "`DownloadAction` SHOULD have `actionStatus` property." ;
+ ] .
+
diff --git a/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json b/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json
index d3823981..d9e2264d 100644
--- a/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json
+++ b/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json
@@ -306,7 +306,7 @@
"@id": "https://w3id.org/shp#DisclosureCheck"
},
"name": "Disclosure check of workflow results: approved",
- "startTime": "2023-04-24T00:00:00+01:00",
+ "startTime": "2023-04-25T15:00:00+01:00",
"endTime": "2023-04-25T16:00:00+01:00",
"object": {
"@id": "./"
diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py
new file mode 100644
index 00000000..d183d0df
--- /dev/null
+++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py
@@ -0,0 +1,517 @@
+# Copyright (c) 2024-2025 CRS4
+#
+# 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.
+
+import logging
+
+from rocrate_validator.models import Severity
+from tests.ro_crates import ValidROC
+from tests.shared import do_entity_test, SPARQL_PREFIXES
+
+# set up logging
+logger = logging.getLogger(__name__)
+
+
+# ----- MUST fails tests
+
+
+def test_5src_download_action_does_not_have_name():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?this schema:name ?name .
+ }
+ WHERE {
+ ?this schema:name ?name ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ "DownloadAction MUST have a human readable name string of at least 10 characters."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_name_not_a_string():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?this schema:name ?name .
+ }
+ INSERT {
+ ?this schema:name 123 .
+ }
+ WHERE {
+ ?this rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ "DownloadAction MUST have a human readable name string of at least 10 characters."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_name_not_long_enough():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?this schema:name ?name .
+ }
+ INSERT {
+ ?this schema:name "Short" .
+ }
+ WHERE {
+ ?this rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ "DownloadAction MUST have a human readable name string of at least 10 characters."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_start_time_not_iso_standard():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?c schema:startTime ?t .
+ }
+ INSERT {
+ ?c schema:startTime "1st of Jan 2021" .
+ }
+ WHERE {
+ ?c rdf:type schema:DownloadAction ;
+ schema:startTime ?t .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard "
+ "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_check_value_end_time_not_iso_standard():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?c schema:endTime ?t .
+ }
+ INSERT {
+ ?c schema:endTime "1st of Jan 2021" .
+ }
+ WHERE {
+ ?c rdf:type schema:DownloadAction ;
+ schema:endTime ?t .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard "
+ "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_downloaded_workflow_same_as_is_not_the_same_as_root_data_entity_main_entity():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?wf schema:sameAs ?me .
+ }
+ INSERT {
+ ?wf schema:sameAs "This is not the same as the main entity" .
+ }
+ WHERE {
+ ?wf schema:sameAs ?me .
+ <./> schema:mainEntity ?me .
+ ?da schema:result ?wf ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["Downloaded Workflow"],
+ expected_triggered_issues=[
+ (
+ "The property `sameAs` of the entity representing the downloaded workflow "
+ "MUST point to the same entity as `RootDataEntity` --> `mainEntity`."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_downloaded_workflow_distribution_is_not_the_same_as_download_action_object():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?s schema:object ?o .
+ }
+ INSERT {
+ ?s schema:result "This is not the downloaded workflow entity" .
+ }
+ WHERE {
+ ?s schema:object ?o ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["Downloaded Workflow"],
+ expected_triggered_issues=[
+ (
+ "DownloadedWorkflow --> `distribution` MUST reference "
+ "the same entity as `DownloadAction` --> `object`."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_has_action_status_with_not_allowed_value():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?s schema:actionStatus ?o .
+ }
+ INSERT {
+ ?s schema:actionStatus "Not a good action status" .
+ }
+ WHERE {
+ ?s rdf:type schema:DownloadAction ;
+ schema:actionStatus ?o .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.REQUIRED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "The value of actionStatus MUST be one of the allowed values: "
+ "PotentialActionStatus; ActiveActionStatus; CompletedActionStatus; FailedActionStatus."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+# ----- SHOULD fails tests
+
+
+def test_5src_download_action_is_not_present():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?da ?p ?o .
+ }
+ WHERE {
+ ?da rdf:type schema:DownloadAction ;
+ ?p ?o .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["RootDataEntity"],
+ expected_triggered_issues=["An entity typed DownloadAction SHOULD exist."],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_root_data_entity_does_not_mention_download_action_entity():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ <./> schema:mentions ?o .
+ }
+ WHERE {
+ ?o rdf:type schema:DownloadAction ;
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["RootDataEntity"],
+ expected_triggered_issues=[
+ "RootDataEntity SHOULD mention DownloadAction if this exists."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_does_not_have_end_time():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?c schema:endTime ?t .
+ }
+ WHERE {
+ ?c rdf:type schema:DownloadAction ;
+ schema:endTime ?t .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "`DownloadAction` SHOULD have the `endTime` property "
+ "if `actionStatus` is either CompletedActionStatus or FailedActionStatus."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?wf ?p ?o .
+ }
+ WHERE {
+ ?wf ?p ?o .
+ ?da schema:result ?wf ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "The entity represented the downloaded workflow is not properly defined in the "
+ "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?s schema:result ?o .
+ }
+ INSERT {
+ ?s schema:result "This is not the downloaded workflow entity" .
+ }
+ WHERE {
+ ?s schema:result ?o ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "The entity represented the downloaded workflow is not properly defined in the "
+ "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_downloaded_workflow_entity_is_not_of_type_dataset():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?wf rdf:type schema:Dataset .
+ }
+ INSERT {
+ ?wf rdf:type schema:Person .
+ }
+ WHERE {
+ ?wf rdf:type schema:Dataset .
+ ?da schema:result ?wf ;
+ rdf:type schema:DownloadAction .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ (
+ "The entity represented the downloaded workflow is not properly defined in the "
+ "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`."
+ )
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+def test_5src_download_action_does_not_have_action_status_property():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?s schema:actionStatus ?o .
+ }
+ WHERE {
+ ?s rdf:type schema:DownloadAction ;
+ schema:actionStatus ?o .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.RECOMMENDED,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ "`DownloadAction` SHOULD have `actionStatus` property."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )
+
+
+# ----- MAY fails tests
+
+
+def test_5src_download_action_does_not_have_start_time():
+ sparql = (
+ SPARQL_PREFIXES
+ + """
+ DELETE {
+ ?c schema:startTime ?t .
+ }
+ WHERE {
+ ?c rdf:type schema:DownloadAction ;
+ schema:startTime ?t .
+ }
+ """
+ )
+
+ do_entity_test(
+ rocrate_path=ValidROC().five_safes_crate_result,
+ requirement_severity=Severity.OPTIONAL,
+ expected_validation_result=False,
+ expected_triggered_requirements=["DownloadAction"],
+ expected_triggered_issues=[
+ "`DownloadAction` MAY have the `startTime` property if `actionStatus` "
+ "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus."
+ ],
+ profile_identifier="five-safes-crate",
+ rocrate_entity_mod_sparql=sparql,
+ )