Getting Started

library(dsROCrate)

# show all the lines in the RO-Crate
oopt <- options(max_lines = Inf)

This tutorial assumes that you have an internet connection and can access OBiBa’s Opal demo server: https://opal-demo.obiba.org

Alternatively, if you want to test a local deployment, please check out the following vignette first:

vignette("deploy-local-datashield-server-with-opal", package = "dsROCrate")

1. Creating your first RO-Crate

Here we are using an administrator account, as this one is available by default on the demo server; however, we recommend you create a dedicated auditing account with the Audit system permission level. See the vignette:

vignette('audit-permissions', package = 'dsROCrate')

for further details.

1.1. Connect to an Opal server

Here we will use OBiBa’s Opal demo server: https://opal-demo.obiba.org/ which can be accessed with the following login credentials:

# define global variables
## Opal server access
USERNAME <- "administrator"
USERPASS <- "password"
SERVER <- "https://opal-demo.obiba.org"
## Credentials for `dsuser`
### NOTE: this is only used to simulate an analysis and generate logs
DSUSERPASS <- "P@ssw0rd"

Next, define global variables used in generating the RO-Crate, such as project name, asset (e.g., tables, resources, etc.) references (within the project) and user identifiers.

## Five safes variables
PEOPLE <- "dsuser"
PROJECT <- "CNSIM"
TABLES <- c("CNSIM1")

Open connection

Once the credentials and Five Safes variables are configured, we can start a new session on the Opal server with the following command:

# login to local server with `USERNAME` and `USERPASS`.
o <- opalr::opal.login(
  username = USERNAME,
  password = USERPASS,
  url = SERVER
)

print(o)
#> url: https://opal-demo.obiba.org 
#> name: opal-demo.obiba.org 
#> version: 5.7.2 
#> username: administrator

1.2. Create a basic RO-Crate

To create a basic RO-Crate, we will use the {rocrateR} package. This package can be installed with the following command:

# install.packages("pak")
pak::pak("rocrateR")

# for development version use
pak::pak("ResearchObject/ro-crate-r@dev")

Then, a basic RO-Crate can be created with the following command:

basic_rocrate <- rocrateR::rocrate_5s()

Note that this RO-Crate uses the 5s-crate profile.

print(basic_rocrate)
#> {
#>   "@context": "https://w3id.org/ro/crate/1.2/context",
#>   "@graph": [
#>     {
#>       "@id": "ro-crate-metadata.json",
#>       "@type": "CreativeWork",
#>       "about": {
#>         "@id": "./"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/ro/crate/1.2"
#>       }
#>     },
#>     {
#>       "@id": "./",
#>       "@type": "Dataset",
#>       "name": "",
#>       "description": "",
#>       "datePublished": "2026-06-01",
#>       "license": {
#>         "@id": "http://spdx.org/licenses/CC-BY-4.0"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/5s-crate/0.4"
#>       }
#>     },
#>     {
#>       "@id": "https://w3id.org/5s-crate/0.4",
#>       "@type": ["CreativeWork", "Profile"],
#>       "name": "Five Safes RO-Crate profile"
#>     }
#>   ]
#> }

1.3. Add the Five Safes Elements

Safe Data

To add details for Safe Data, use the function dsROCrate::safe_data().

basic_rocrate <- o |>
  dsROCrate::safe_data(rocrate = basic_rocrate,
                       project = PROJECT,
                       tables = TABLES)

print(basic_rocrate) # note that the output will be truncated
...
#>     {
#>       "@id": "#perm:1624c2b25e0d766e47e6ed8a650de30b-admin-table",
#>       "@type": "ControlAction",
#>       "agent": {
#>         "@id": "#person:601292e86f700c37deb64fd70ac36f5e"
#>       },
#>       "object": {
#>         "@id": "#asset:fad6faf661584d53e58f9730b14c5aae"
#>       },
#>       "actionStatus": "PotentialActionStatus",
#>       "description": "User has full administrative rights: view/edit dictionary and view/edit individual values."
#>     },
#>     {
#>       "@id": "#perm:9bf7f75b6c5b07d02830b95652cd39a0-dict-summary-read",
#>       "@type": "ReadAction",
#>       "agent": {
#>         "@id": "#person:a0af2a94926db1b49ad7a812eef509d2"
#>       },
#>       "object": {
#>         "@id": "#asset:fad6faf661584d53e58f9730b14c5aae"
#>       },
#>       "actionStatus": "PotentialActionStatus",
#>       "description": "User may view table dictionary and summary statistics only; access to individual values is restricted."
#>     },
#>     {
#>       "@id": "#perm:4d2673da68a58c3bce23a61d97b6df51-dict-summary-read",
#>       "@type": "ReadAction",
#>       "agent": {
#>         "@id": "#person:cb809df1c2fb30b154f60b843e62b3d0"
#>       },
#>       "object": {
#>         "@id": "#asset:fad6faf661584d53e58f9730b14c5aae"
#>       },
#>       "actionStatus": "PotentialActionStatus",
#>       "description": "User may view table dictionary and summary statistics only; access to individual values is restricted."
#>     },
#>     {
#>       "@id": "#perm:1f09051d217d17c3e9b5ed92819ded26-admin-table",
#>       "@type": "ControlAction",
#>       "agent": {
#>         "@id": "#person:a3bc19cc9c1269320cf2847c63a66a92"
#>       },
#>       "object": {
#>         "@id": "#asset:fad6faf661584d53e58f9730b14c5aae"
#>       },
#>       "actionStatus": "PotentialActionStatus",
#>       "description": "User has full administrative rights: view/edit dictionary and view/edit individual values."
#>     },
#>     {
#>       "@id": "#asset:fad6faf661584d53e58f9730b14c5aae",
#>       "@type": "Dataset",
#>       "name": "CNSIM1",
#>       "description": "",
#>       "url": "/datasource/CNSIM/table/CNSIM1",
#>       "dateCreated": "2026-06-01T00:00:00Z",
#>       "dateModified": "2026-06-01T00:00:00Z",
#>       "isPartOf": {
#>         "@id": "#project:7ba189863f9f641196596cb28e04aa14"
#>       }
#>     }
#>   ]
#> }

Safe Project

To add details for Safe Project, use the function dsROCrate::safe_project().

basic_rocrate <- o |>
  dsROCrate::safe_project(rocrate = basic_rocrate,
                          project = PROJECT)

print(basic_rocrate) # note that the output will be truncated
...
#>       ]
#>     },
#>     {
#>       "@id": "#project:7ba189863f9f641196596cb28e04aa14",
#>       "@type": "Project",
#>       "name": "CNSIM",
#>       "dateCreated": "2026-06-01T06:30:09.645Z",
#>       "dateModified": "2026-06-01T06:30:14.859Z",
#>       "hasPart": [
#>         {
#>           "@id": "#asset:fad6faf661584d53e58f9730b14c5aae"
#>         }
#>       ]
#>     }
#>   ]
#> }

Safe People

To add details for Safe People, use the function dsROCrate::safe_people().

basic_rocrate <- o |>
  dsROCrate::safe_people(rocrate = basic_rocrate, user = PEOPLE)

print(basic_rocrate) # note that the output will be truncated
...
#>     {
#>       "@id": "#person:a0af2a94926db1b49ad7a812eef509d2",
#>       "@type": "Person",
#>       "name": "dsuser"
#>     }
#>   ]
#> }

Safe Setting

To add details for Safe Setting, use the function dsROCrate::safe_setting().

ⓘ️ NOTE: The dsROCrate::safe_setting function requires administrator or auditor privileges, so here, we will have to log in with administrator credentials (if you used a non-administrator/auditor account previously).

# close previous connection
opalr::opal.logout(o)

# open new connection as administrator
o <- opalr::opal.login(
  username = "administrator",
  password = "password",
  url = SERVER
)

Then, we can proceed as per usual:

basic_rocrate <- o |>
  dsROCrate::safe_setting(rocrate = basic_rocrate)

print(basic_rocrate) # note that the output will be truncated
...
#>     {
#>       "@id": "#disc:27d8c1d2233ecb654a24b635fd4dbd78",
#>       "@type": "PropertyValue",
#>       "name": "datashield.privacyLevel",
#>       "value": "5"
#>     },
#>     {
#>       "@id": "#disc:46b65707a6b998f3b1364bc10e6d9b4b",
#>       "@type": "PropertyValue",
#>       "name": "default.datashield.privacyControlLevel",
#>       "value": "banana"
#>     },
#>     {
#>       "@id": "#disc:7769282e7b0a1cb8887f60886c7b56ae",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.glm",
#>       "value": "0.33"
#>     },
#>     {
#>       "@id": "#disc:49d822f52075aafbec1d1b2545aa46b7",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.kNN",
#>       "value": "3"
#>     },
#>     {
#>       "@id": "#disc:9a59210a743557bbd61cb21c3f1e0a79",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.levels.density",
#>       "value": "0.33"
#>     },
#>     {
#>       "@id": "#disc:a00b1e31a448142ee66bbb013f990e1f",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.levels.max",
#>       "value": "40"
#>     },
#>     {
#>       "@id": "#disc:29dd5e27a9f1c66d81a7037c236e7dd5",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.noise",
#>       "value": "0.25"
#>     },
#>     {
#>       "@id": "#disc:1c12e549b91e2cc0856f56657988ce54",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.string",
#>       "value": "80"
#>     },
#>     {
#>       "@id": "#disc:786bc0ffcdd3054925e431240caecea5",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.stringShort",
#>       "value": "20"
#>     },
#>     {
#>       "@id": "#disc:fd9bea5ef311d5f14b28d237ecb6e985",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.subset",
#>       "value": "3"
#>     },
#>     {
#>       "@id": "#disc:4e93a50cbd8cfea8f0a6adc50ee7aac0",
#>       "@type": "PropertyValue",
#>       "name": "default.nfilter.tab",
#>       "value": "3"
#>     },
#>     {
#>       "@id": "#env:disclosure_settings:7d746edc2fb36ee671241a333742b3a8",
#>       "@type": "CreativeWork",
#>       "name": "Disclosure Control Environment",
#>       "description": "Disclosure control settings extract from the OBiBa Opal server connection provided, using the profile: 'default'.",
#>       "hasPart": [
#>         {
#>           "@id": "#disc:27d8c1d2233ecb654a24b635fd4dbd78"
#>         },
#>         {
#>           "@id": "#disc:46b65707a6b998f3b1364bc10e6d9b4b"
#>         },
#>         {
#>           "@id": "#disc:7769282e7b0a1cb8887f60886c7b56ae"
#>         },
#>         {
#>           "@id": "#disc:49d822f52075aafbec1d1b2545aa46b7"
#>         },
#>         {
#>           "@id": "#disc:9a59210a743557bbd61cb21c3f1e0a79"
#>         },
#>         {
#>           "@id": "#disc:a00b1e31a448142ee66bbb013f990e1f"
#>         },
#>         {
#>           "@id": "#disc:29dd5e27a9f1c66d81a7037c236e7dd5"
#>         },
#>         {
#>           "@id": "#disc:1c12e549b91e2cc0856f56657988ce54"
#>         },
#>         {
#>           "@id": "#disc:786bc0ffcdd3054925e431240caecea5"
#>         },
#>         {
#>           "@id": "#disc:fd9bea5ef311d5f14b28d237ecb6e985"
#>         },
#>         {
#>           "@id": "#disc:4e93a50cbd8cfea8f0a6adc50ee7aac0"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "#software:f8784d80bad08f840fba23fa9c41ec27",
#>       "@type": "SoftwareApplication",
#>       "name": "dsBase",
#>       "version": "6.3.5",
#>       "description": "Base 'DataSHIELD' functions for the server side. 'DataSHIELD' is a software package which allows you to do non-disclosive federated analysis on sensitive data. 'DataSHIELD' analytic functions have been designed to only share non disclosive summary statistics, with built in automated output checking based on statistical disclosure control. With data sites setting the threshold values for the automated output checks. For more details, see 'citation(\"dsBase\")'."
#>     },
#>     {
#>       "@id": "#software:9c282917cfea3f37d5c5777c9aa6668d",
#>       "@type": "SoftwareApplication",
#>       "name": "dsTidyverse",
#>       "version": "1.2.1",
#>       "description": "Implementation of selected 'Tidyverse' functions within 'DataSHIELD', an open-source federated analysis solution in R. Currently, DataSHIELD contains very limited tools for data manipulation, so the aim of this package is to improve the researcher experience by implementing essential functions for data manipulation, including subsetting, filtering, grouping, and renaming variables. This is the server-side package which should be installed on the server holding the data, and is used in conjunction with the client-side package 'dsTidyverseClient' which is installed in the local R environment of the analyst. For more information, see <https://tidyverse.org/> and <https://datashield.org/>."
#>     },
#>     {
#>       "@id": "#software:73f9cc9367c85ea883898394daf3821a",
#>       "@type": "SoftwareApplication",
#>       "name": "resourcer",
#>       "version": "1.5.1",
#>       "description": "A resource represents some data or a computation unit. It is described by a URL and credentials. This package proposes a Resource model with \"resolver\" and \"client\" classes to facilitate the access and the usage of the resources."
#>     },
#>     {
#>       "@id": "#software:a2de0349822076014ea98bb1d4d31dae",
#>       "@type": "SoftwareApplication",
#>       "name": "Opal",
#>       "version": "5.7.2",
#>       "description": "Opal is OBiBa's (https://www.obiba.org/) core database application for epidemiological studies. Participant data, collected by questionnaires, medical instruments, sensors, administrative databases etc. can be integrated and stored in a central data repository under a uniform model."
#>     },
#>     {
#>       "@id": "#env:software_stack:3ae2db187301d4cb44c52f30ec57fbaf",
#>       "@type": "CreativeWork",
#>       "name": "Approved Analytical Software Environment",
#>       "description": "Software packages installed in the controlled Opal/DataSHIELD environment used for federated analysis.",
#>       "hasPart": [
#>         {
#>           "@id": "#software:f8784d80bad08f840fba23fa9c41ec27"
#>         },
#>         {
#>           "@id": "#software:9c282917cfea3f37d5c5777c9aa6668d"
#>         },
#>         {
#>           "@id": "#software:73f9cc9367c85ea883898394daf3821a"
#>         },
#>         {
#>           "@id": "#software:a2de0349822076014ea98bb1d4d31dae"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "#control:output-checking",
#>       "@type": "CreativeWork",
#>       "name": "Statistical Disclosure Output Checking",
#>       "description": "Automated disclosure control prevents release of small-cell counts and disclosive statistics."
#>     },
#>     {
#>       "@id": "#control:server-side-analysis",
#>       "@type": "CreativeWork",
#>       "name": "Server-Side Analysis Enforcement",
#>       "description": "Raw data never leaves the secure server; analysis occurs via vetted aggregate functions."
#>     },
#>     {
#>       "@id": "#control:session-logging",
#>       "@type": "CreativeWork",
#>       "name": "Comprehensive Session Logging",
#>       "description": "All analytical actions are logged and auditable."
#>     },
#>     {
#>       "@id": "#control:secure-facility",
#>       "@type": "CreativeWork",
#>       "name": "Secure Data Facility",
#>       "description": "Access restricted to approved secure premises."
#>     },
#>     {
#>       "@id": "#control:access-governance",
#>       "@type": "CreativeWork",
#>       "name": "Access Governance Process",
#>       "description": "Data access committee review and approval required."
#>     },
#>     {
#>       "@id": "#safesetting:8489860e7540c5dfb95b5d8ddab232c5",
#>       "@type": "CreativeWork",
#>       "name": "Safe Setting Controls (Opal)",
#>       "description": "Technical, physical and organisational safeguards applied to minimise disclosure risk.",
#>       "hasPart": [
#>         {
#>           "@id": "#env:disclosure_settings:7d746edc2fb36ee671241a333742b3a8"
#>         },
#>         {
#>           "@id": "#env:software_stack:3ae2db187301d4cb44c52f30ec57fbaf"
#>         },
#>         {
#>           "@id": "#control:output-checking"
#>         },
#>         {
#>           "@id": "#control:server-side-analysis"
#>         },
#>         {
#>           "@id": "#control:session-logging"
#>         },
#>         {
#>           "@id": "#control:secure-facility"
#>         },
#>         {
#>           "@id": "#control:access-governance"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "#link:b16fbdedcc33e826878020dcd5fad3d3",
#>       "@type": "CreativeWork",
#>       "name": "Safe Settings x Safe Project Link",
#>       "about": {
#>         "@id": "#safesetting:8489860e7540c5dfb95b5d8ddab232c5"
#>       },
#>       "isPartOf": {
#>         "@id": "#project:7ba189863f9f641196596cb28e04aa14"
#>       }
#>     }
#>   ]
#> }

Safe Outputs

To add details for Safe Outputs, use the function dsROCrate::safe_output(). Currently, only log files from the operations executed by the user within a specific period. Set the period using logs_from and logs_to. Additionally, a list of functions executed by the user are extracted in a separate file/entity.

ⓘ NOTE: Similar to dsROCrate::safe_setting, the dsROCrate::safe_output function requires of administrator or auditor privileges, so here, we will have to log in with administrator/auditor credentials:

# close previous connection
opalr::opal.logout(o)

# open new connection as administrator
o <- opalr::opal.login(
  username = "administrator",
  password = "password",
  url = SERVER
)

DataSHIELD operations

ⓘ NOTE: Before extracting logs, ensure there is recent activity on the server for testing purposes. This can be done using the following commands:

Setup

You will need the following packages:

pak::pak("DSI")
pak::pak("DSOpal")
pak::pak("dsBaseClient")
Open connection
# run some test commands with dsBaseClient
## needed to defined the OpalDriver class in the current environment
DSOpal::Opal()
#> An object of class "OpalDriver"
#> <S4 Type Object>
## create new login object, note that here we use the `dsuser`
builder <- DSI::newDSLoginBuilder()
builder$append(server = "study1",
               url = SERVER,
               user = "dsuser",
               password = DSUSERPASS,
               driver = "OpalDriver")
logindata <- builder$build()
conns <- DSI::datashield.login(logins = logindata)
#> 
#> Logging into the collaborating servers
Simulate some operations
## assign data
DSI::datashield.assign.table(conns["study1"], 
                             symbol = "dsROCrate_test",
                             table = paste0(PROJECT, ".", TABLES[1]),
                             errors.print = TRUE)

dsBaseClient::ds.ls(datasources = conns["study1"])
#> $study1
#> $study1$environment.searched
#> [1] "R_GlobalEnv"
#> 
#> $study1$objects.found
#> [1] "dsROCrate_test"
dsBaseClient::ds.summary("dsROCrate_test")
#> $study1
#> $study1$class
#> [1] "data.frame"
#> 
#> $study1$`number of rows`
#> [1] 2163
#> 
#> $study1$`number of columns`
#> [1] 11
#> 
#> $study1$`variables held`
#>  [1] "LAB_TSC"            "LAB_TRIG"           "LAB_HDL"           
#>  [4] "LAB_GLUC_ADJUSTED"  "PM_BMI_CONTINUOUS"  "DIS_CVA"           
#>  [7] "MEDI_LPD"           "DIS_DIAB"           "DIS_AMI"           
#> [10] "GENDER"             "PM_BMI_CATEGORICAL"

Then, we can proceed as per usual:

basic_rocrate <- o |>
  dsROCrate::safe_output(rocrate = basic_rocrate,
                         logs_from = Sys.time() - 8.64E4, # capture the last 24 hours
                         logs_to = Sys.time())
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> Warning: A `path` wasn't provided! The logs will be included in the RO-Crate
#> object, under the `content` tag!
print(basic_rocrate) # note that the output will be truncated
...
#>     {
#>       "@id": "20260601T131737-dslogs-dsuser.log",
#>       "@type": "File",
#>       "dateModified": "2026-06-01 13:17:37",
#>       "name": "20260601T131737-dslogs-dsuser.log",
#>       "description": "This file contains the raw logs for the user: `dsuser` , between: 2026-05-31 13:17:36 and 2026-06-01 13:17:36",
#>       "encodingFormat": "text/plain",
#>       "content": [
#>         ["[INFO][2026-06-01T07:37:01][OPEN]      created a datashield session 0150d756-3f22-407f-ba1b-245bc8cf5ab0", "[INFO][2026-06-01T07:37:03][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T07:37:03][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T07:37:04][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T07:37:04][PARSE]     parsed 'base::exists(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:04][AGGREGATE] evaluated 'base::exists(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:04][PARSE]     parsed 'dsBase::classDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:04][AGGREGATE] evaluated 'dsBase::classDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:04][PARSE]     parsed 'dsBase::isValidDS(dsROCrate_test)'", "[INFO][2026-06-01T07:37:04][AGGREGATE] evaluated 'dsBase::isValidDS(dsROCrate_test)'", "[INFO][2026-06-01T07:37:05][PARSE]     parsed 'dsBase::dimDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:05][AGGREGATE] evaluated 'dsBase::dimDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:05][PARSE]     parsed 'dsBase::colnamesDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:37:05][AGGREGATE] evaluated 'dsBase::colnamesDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T07:39:08][OPEN]      created a datashield session 725e11d4-a677-49ed-a8fa-82c58e0b3210", "[INFO][2026-06-01T07:39:08][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T07:39:08][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T07:39:09][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T08:21:05][OPEN]      created a datashield session 924db769-298d-4c7b-bc60-a0b760c03447", "[INFO][2026-06-01T08:21:06][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T08:21:06][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T08:21:07][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T09:24:09][OPEN]      created a datashield session 4b585110-6ab0-458c-8986-363b750a1cc3", "[INFO][2026-06-01T09:24:09][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T09:24:10][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T09:24:10][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T09:24:11][PARSE]     parsed 'base::exists(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][AGGREGATE] evaluated 'base::exists(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][PARSE]     parsed 'dsBase::classDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][AGGREGATE] evaluated 'dsBase::classDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][PARSE]     parsed 'dsBase::isValidDS(dsROCrate_test)'", "[INFO][2026-06-01T09:24:11][AGGREGATE] evaluated 'dsBase::isValidDS(dsROCrate_test)'", "[INFO][2026-06-01T09:24:11][PARSE]     parsed 'dsBase::dimDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][AGGREGATE] evaluated 'dsBase::dimDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][PARSE]     parsed 'dsBase::colnamesDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:24:11][AGGREGATE] evaluated 'dsBase::colnamesDS(\"dsROCrate_test\")'", "[INFO][2026-06-01T09:49:44][OPEN]      created a datashield session 8923e215-dba7-4d71-8fe5-5840623a40f4", "[INFO][2026-06-01T09:49:44][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T09:49:45][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T09:49:45][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T10:24:03][OPEN]      created a datashield session 2a13ced8-e23d-4448-9aea-a3c7ca47c85c", "[INFO][2026-06-01T10:24:03][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T10:24:04][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T10:24:05][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T10:55:52][OPEN]      created a datashield session 8161f0a4-e17a-4fc3-9184-e4eb0619c270", "[INFO][2026-06-01T10:55:52][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T10:55:53][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T10:55:54][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T12:14:09][OPEN]      created a datashield session 0544d264-3571-4a22-9f9c-bb6420211846", "[INFO][2026-06-01T12:14:10][ASSIGN]    created symbol 'dsROCrate_test' from: 'dsROCrate_test <- opal[CNSIM.CNSIM1]'", "[INFO][2026-06-01T12:14:10][PARSE]     parsed 'dsBase::lsDS(search.filter = NULL, 1L)'", "[INFO][2026-06-01T12:14:11][AGGREGATE] evaluated 'dsBase::lsDS(search.filter = NULL, 1L)'"]
#>       ]
#>     },
#>     {
#>       "@id": "20260601T131737-dslogs-dsuser_mappings.csv",
#>       "@type": "File",
#>       "dateModified": "2026-06-01 13:17:37",
#>       "name": "20260601T131737-dslogs-dsuser_mappings.csv",
#>       "description": "This file contains mappings and evaluated functions",
#>       "encodingFormat": "text/csv",
#>       "content": [
#>         [
#>           {
#>             "timestamp": "2026-06-01T07:37:01",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "fx": "DSI::datashield.login",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:03",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:04",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:04",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "base::exists(\"dsROCrate_test\")",
#>             "fx": "base::exists",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:04",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::classDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::classDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:04",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::isValidDS(dsROCrate_test)",
#>             "fx": "dsBase::isValidDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:05",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::dimDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::dimDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:37:05",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::colnamesDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::colnamesDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0150d756-3f22-407f-ba1b-245bc8cf5ab0",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:39:08",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 725e11d4-a677-49ed-a8fa-82c58e0b3210",
#>             "fx": "DSI::datashield.login",
#>             "session": "725e11d4-a677-49ed-a8fa-82c58e0b3210",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:39:08",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "725e11d4-a677-49ed-a8fa-82c58e0b3210",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T07:39:09",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "725e11d4-a677-49ed-a8fa-82c58e0b3210",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T08:21:05",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 924db769-298d-4c7b-bc60-a0b760c03447",
#>             "fx": "DSI::datashield.login",
#>             "session": "924db769-298d-4c7b-bc60-a0b760c03447",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T08:21:06",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "924db769-298d-4c7b-bc60-a0b760c03447",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T08:21:07",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "924db769-298d-4c7b-bc60-a0b760c03447",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:09",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "fx": "DSI::datashield.login",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:09",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:10",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "base::exists(\"dsROCrate_test\")",
#>             "fx": "base::exists",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::classDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::classDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::isValidDS(dsROCrate_test)",
#>             "fx": "dsBase::isValidDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::dimDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::dimDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:24:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::colnamesDS(\"dsROCrate_test\")",
#>             "fx": "dsBase::colnamesDS",
#>             "symbol": "dsROCrate_test",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "4b585110-6ab0-458c-8986-363b750a1cc3",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:49:44",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 8923e215-dba7-4d71-8fe5-5840623a40f4",
#>             "fx": "DSI::datashield.login",
#>             "session": "8923e215-dba7-4d71-8fe5-5840623a40f4",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:49:44",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "8923e215-dba7-4d71-8fe5-5840623a40f4",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T09:49:45",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "8923e215-dba7-4d71-8fe5-5840623a40f4",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:24:03",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 2a13ced8-e23d-4448-9aea-a3c7ca47c85c",
#>             "fx": "DSI::datashield.login",
#>             "session": "2a13ced8-e23d-4448-9aea-a3c7ca47c85c",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:24:03",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "2a13ced8-e23d-4448-9aea-a3c7ca47c85c",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:24:05",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "2a13ced8-e23d-4448-9aea-a3c7ca47c85c",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:55:52",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 8161f0a4-e17a-4fc3-9184-e4eb0619c270",
#>             "fx": "DSI::datashield.login",
#>             "session": "8161f0a4-e17a-4fc3-9184-e4eb0619c270",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:55:52",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "8161f0a4-e17a-4fc3-9184-e4eb0619c270",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T10:55:54",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "8161f0a4-e17a-4fc3-9184-e4eb0619c270",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T12:14:09",
#>             "action": "OPEN",
#>             "user": "dsuser",
#>             "r_cmd": "Open session: 0544d264-3571-4a22-9f9c-bb6420211846",
#>             "fx": "DSI::datashield.login",
#>             "session": "0544d264-3571-4a22-9f9c-bb6420211846",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T12:14:10",
#>             "action": "ASSIGN",
#>             "user": "dsuser",
#>             "r_cmd": "dsROCrate_test <- opal[CNSIM.CNSIM1]",
#>             "fx": "base::assign",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0544d264-3571-4a22-9f9c-bb6420211846",
#>             "backend": "OBiBa's Opal"
#>           },
#>           {
#>             "timestamp": "2026-06-01T12:14:11",
#>             "action": "AGGREGATE",
#>             "user": "dsuser",
#>             "r_cmd": "dsBase::lsDS(search.filter = NULL, 1L)",
#>             "fx": "dsBase::lsDS",
#>             "symbol": "search.filter = NULL, 1L",
#>             "table": "CNSIM.CNSIM1",
#>             "session": "0544d264-3571-4a22-9f9c-bb6420211846",
#>             "backend": "OBiBa's Opal"
#>           }
#>         ]
#>       ]
#>     }
#>   ]
#> }

1.4. Close connection

opalr::opal.logout(o)

1.5. Bag/Save RO-Crate

The resulting RO-Crate can be stored into an RO-Crate bag/archive with the function rocrateR::bag_rocrate:

# create temp directory (only for demo purposes)
tmp_path_bag <- file.path(tempdir(), "dsROCrate-getting-started")
dir.create(tmp_path_bag, showWarnings = FALSE)

# create RO-Crate bag
path_to_rocrate_bag <- basic_rocrate |>
  rocrateR::bag_rocrate(path = tmp_path_bag, overwrite = TRUE)
#> RO-Crate successfully 'bagged'!
#> For details, see: /var/folders/59/4_l6kbyj2qsczmk2b52qg_f40000gn/T//RtmpY0wZ5T/dsROCrate-getting-started/rocrate-e2bac940f60b8867ca8c3d6e04a993a9.zip

We can explore the contents with the following commands:

# extract files in temporary directory
path_to_rocrate_bag |>
  # extract contents inside /tmp_path_bag/ROC
  rocrateR::unbag_rocrate(output = file.path(tmp_path_bag, "ROC"), quiet = TRUE) |>
  # create tree with the files
  fs::dir_tree()
#> /private/var/folders/59/4_l6kbyj2qsczmk2b52qg_f40000gn/T/RtmpY0wZ5T/dsROCrate-getting-started/ROC
#> ├── bag-info.txt
#> ├── bagit.txt
#> ├── data
#> │   ├── 20260601T131737-dslogs-dsuser.log
#> │   ├── 20260601T131737-dslogs-dsuser_mappings.csv
#> │   └── ro-crate-metadata.json
#> ├── manifest-sha512.txt
#> └── tagmanifest-sha512.txt

1.6. Clean working directory

unlink(tmp_path_bag, recursive = TRUE, force = TRUE)


2. Auditing RO-Crates and servers

2.1. Audit People

List accessible tables within a project for an user
safe_people_crate_v1 <- opalr::opal.login(
  username = USERNAME,
  password = USERPASS,
  url = SERVER
) |>
  dsROCrate::audit(user = "dsuser", project = "CNSIM")
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.

print(safe_people_crate_v1)
#> {
#>   "@context": "https://w3id.org/ro/crate/1.2/context",
#>   "@graph": [
#>     {
#>       "@id": "ro-crate-metadata.json",
#>       "@type": "CreativeWork",
#>       "about": {
#>         "@id": "./"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/ro/crate/1.2"
#>       }
#>     },
#>     {
#>       "@id": "./",
#>       "@type": "Dataset",
#>       "name": "",
#>       "description": "",
#>       "datePublished": "2026-06-01",
#>       "license": {
#>         "@id": "http://spdx.org/licenses/CC-BY-4.0"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/5s-crate/0.4"
#>       },
#>       "hasPart": [
#>         {
#>           "@id": "20260601T131740-dslogs-dsuser.log"
#>         },
#>         {
#>           "@id": "20260601T131740-dslogs-dsuser_mappings.csv"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "https://w3id.org/5s-crate/0.4",
#>       "@type": ["CreativeWork", "Profile"],
#>       "name": "Five Safes RO-Crate profile"
#>   ❗ <file truncated, set `options(max_lines = Inf)` to display all>
#>   ]
#> }
Markdown report

A markdown report can be created with an overview and details for an RO-Crate, using the dsROCrate::report:

Only generate .Rmd file

safe_people_crate_v1_rmd <- tempfile(fileext = ".Rmd") # temporary file

safe_people_crate_contents <- safe_people_crate_v1 |>
  dsROCrate::report(filepath = safe_people_crate_v1_rmd, render = FALSE)
#> 1 'Author' entity was found!
#> 3 asset entities were found!
#> 1 'Project' entity was found!
#> 22 'CreativeWork', 'PropertyValue' OR 'SoftwareApplication' entities were found!
#> 2 'File' entities were found!

# display Overview diagram
safe_people_crate_contents$overview_diagram

# display Overview data (Safe People, Safe Projects and Safe Data)
safe_people_crate_contents$overview_data |>
  knitr::kable()
Project Data Access Level People Function Timestamp
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:37:03
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser base::exists 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T07:37:05
CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T07:37:05
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:39:08
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:39:09
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T08:21:06
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T08:21:07
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:24:09
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:24:10
CNSIM CNSIM1 read dsuser base::exists 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:49:44
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:49:45
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:24:03
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:24:05
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:55:52
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:55:54
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T12:14:10
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T12:14:11
CNSIM CNSIM2 read dsuser
CNSIM CNSIM3 read dsuser

Render and display report (HTML)

safe_people_crate_v1 |>
  dsROCrate::report(filepath = safe_people_crate_v1_rmd,
                            title = "DataSHIELD Safe People - Audit Report",
                            render = TRUE, 
                            overwrite = TRUE)

2.2. Audit Project

List users and dataset/table level permissions within a project
safe_project_crate_v1 <- opalr::opal.login(
  username = USERNAME,
  password = USERPASS,
  url = SERVER
) |>
  dsROCrate::audit(project = "CNSIM")
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.

print(safe_project_crate_v1)
#> {
#>   "@context": "https://w3id.org/ro/crate/1.2/context",
#>   "@graph": [
#>     {
#>       "@id": "ro-crate-metadata.json",
#>       "@type": "CreativeWork",
#>       "about": {
#>         "@id": "./"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/ro/crate/1.2"
#>       }
#>     },
#>     {
#>       "@id": "./",
#>       "@type": "Dataset",
#>       "name": "",
#>       "description": "",
#>       "datePublished": "2026-06-01",
#>       "license": {
#>         "@id": "http://spdx.org/licenses/CC-BY-4.0"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/5s-crate/0.4"
#>       },
#>       "hasPart": [
#>         {
#>           "@id": "20260601T131744-dslogs-dsuser.log"
#>         },
#>         {
#>           "@id": "20260601T131744-dslogs-dsuser_mappings.csv"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "https://w3id.org/5s-crate/0.4",
#>       "@type": ["CreativeWork", "Profile"],
#>       "name": "Five Safes RO-Crate profile"
#>   ❗ <file truncated, set `options(max_lines = Inf)` to display all>
#>   ]
#> }
Markdown report

A markdown report can be created with an overview and details for an RO-Crate, using the dsROCrate::report:

Only generate .Rmd file

safe_project_crate_v1_rmd <- tempfile(fileext = ".Rmd") # temporary file

safe_project_crate_contents <- safe_project_crate_v1 |>
  dsROCrate::report(filepath = safe_project_crate_v1_rmd, render = FALSE)
#> 5 'Author' entities were found!
#> 3 asset entities were found!
#> 1 'Project' entity was found!
#> 22 'CreativeWork', 'PropertyValue' OR 'SoftwareApplication' entities were found!
#> 2 'File' entities were found!

# display Overview diagram
safe_project_crate_contents$overview_diagram

# display Overview data (Safe People, Safe Projects and Safe Data)
safe_project_crate_contents$overview_data |>
  knitr::kable()
Project Data Access Level People Function Timestamp
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:37:03
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser base::exists 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T07:37:04
CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T07:37:05
CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T07:37:05
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:39:08
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:39:09
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T08:21:06
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T08:21:07
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:24:09
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:24:10
CNSIM CNSIM1 read dsuser base::exists 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T09:24:11
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:49:44
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:49:45
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:24:03
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:24:05
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:55:52
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:55:54
CNSIM CNSIM1 read dsuser base::assign 2026-06-01T12:14:10
CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T12:14:11
CNSIM CNSIM1 read dsuser1
CNSIM CNSIM2 read dsuser
CNSIM CNSIM2 read dsuser2
CNSIM CNSIM3 read dsuser
CNSIM CNSIM3 read dsuser3

Render and display report (HTML)

safe_project_crate_v1 |>
  dsROCrate::report(filepath = safe_project_crate_v1_rmd, 
                            title = "DataSHIELD Safe Project - Audit Report",
                            render = TRUE, 
                            overwrite = TRUE)


2.3. Audit Study

List users and dataset/table level permissions within a study (i.e., multiple servers)
study_crate_v1 <- 
  list(
    "opal_test" = opalr::opal.login(
      username = USERNAME,
      password = USERPASS,
      url = "https://opal-demo.obiba.org"
    ),
    "opal_demo" = opalr::opal.login(
      username = USERNAME,
      password = USERPASS,
      url = "https://opal-demo.obiba.org"
    )
  ) |>
  dsROCrate::audit(project = "CNSIM")
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.
#> opening file input connection.
#>  Found 94 records... Imported 94 records. Simplifying...
#> closing file input connection.

print(study_crate_v1)
#> $opal_test
#> {
#>   "@context": "https://w3id.org/ro/crate/1.2/context",
#>   "@graph": [
#>     {
#>       "@id": "ro-crate-metadata.json",
#>       "@type": "CreativeWork",
#>       "about": {
#>         "@id": "./"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/ro/crate/1.2"
#>       }
#>     },
#>     {
#>       "@id": "./",
#>       "@type": "Dataset",
#>       "name": "",
#>       "description": "",
#>       "datePublished": "2026-06-01",
#>       "license": {
#>         "@id": "http://spdx.org/licenses/CC-BY-4.0"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/5s-crate/0.4"
#>       },
#>       "hasPart": [
#>         {
#>           "@id": "20260601T131749-dslogs-dsuser.log"
#>         },
#>         {
#>           "@id": "20260601T131749-dslogs-dsuser_mappings.csv"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "https://w3id.org/5s-crate/0.4",
#>       "@type": ["CreativeWork", "Profile"],
#>       "name": "Five Safes RO-Crate profile"
#>   ❗ <file truncated, set `options(max_lines = Inf)` to display all>
#>   ]
#> }
#> 
#> $opal_demo
#> {
#>   "@context": "https://w3id.org/ro/crate/1.2/context",
#>   "@graph": [
#>     {
#>       "@id": "ro-crate-metadata.json",
#>       "@type": "CreativeWork",
#>       "about": {
#>         "@id": "./"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/ro/crate/1.2"
#>       }
#>     },
#>     {
#>       "@id": "./",
#>       "@type": "Dataset",
#>       "name": "",
#>       "description": "",
#>       "datePublished": "2026-06-01",
#>       "license": {
#>         "@id": "http://spdx.org/licenses/CC-BY-4.0"
#>       },
#>       "conformsTo": {
#>         "@id": "https://w3id.org/5s-crate/0.4"
#>       },
#>       "hasPart": [
#>         {
#>           "@id": "20260601T131754-dslogs-dsuser.log"
#>         },
#>         {
#>           "@id": "20260601T131754-dslogs-dsuser_mappings.csv"
#>         }
#>       ]
#>     },
#>     {
#>       "@id": "https://w3id.org/5s-crate/0.4",
#>       "@type": ["CreativeWork", "Profile"],
#>       "name": "Five Safes RO-Crate profile"
#>   ❗ <file truncated, set `options(max_lines = Inf)` to display all>
#>   ]
#> }
Markdown report

A markdown report can be created with an overview and details for an RO-Crate, using the dsROCrate::report:

Only generate .Rmd file

study_crate_v1_rmd <- tempfile(fileext = ".Rmd") # temporary file

safe_project_crate_contents <- study_crate_v1 |>
  dsROCrate::report(filepath = study_crate_v1_rmd, render = FALSE)
#> 5 'Author' entities were found!
#> 3 asset entities were found!
#> 1 'Project' entity was found!
#> 22 'CreativeWork', 'PropertyValue' OR 'SoftwareApplication' entities were found!
#> 2 'File' entities were found!
#> 5 'Author' entities were found!
#> 3 asset entities were found!
#> 1 'Project' entity was found!
#> 22 'CreativeWork', 'PropertyValue' OR 'SoftwareApplication' entities were found!
#> 2 'File' entities were found!

# display Overview diagram
safe_project_crate_contents$overview_diagram

# display Overview data (Safe People, Safe Projects and Safe Data)
safe_project_crate_contents$overview_data |>
  knitr::kable()
Server Project Data Access Level People Function Timestamp
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:37:03
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:37:04
opal_demo CNSIM CNSIM1 read dsuser base::exists 2026-06-01T07:37:04
opal_demo CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T07:37:04
opal_demo CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T07:37:04
opal_demo CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T07:37:05
opal_demo CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T07:37:05
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:39:08
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:39:09
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T08:21:06
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T08:21:07
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:24:09
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:24:10
opal_demo CNSIM CNSIM1 read dsuser base::exists 2026-06-01T09:24:11
opal_demo CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T09:24:11
opal_demo CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T09:24:11
opal_demo CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T09:24:11
opal_demo CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T09:24:11
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:49:44
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:49:45
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:24:03
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:24:05
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:55:52
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:55:54
opal_demo CNSIM CNSIM1 read dsuser base::assign 2026-06-01T12:14:10
opal_demo CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T12:14:11
opal_demo CNSIM CNSIM1 read dsuser1
opal_demo CNSIM CNSIM2 read dsuser
opal_demo CNSIM CNSIM2 read dsuser2
opal_demo CNSIM CNSIM3 read dsuser
opal_demo CNSIM CNSIM3 read dsuser3
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:37:03
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:37:04
opal_test CNSIM CNSIM1 read dsuser base::exists 2026-06-01T07:37:04
opal_test CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T07:37:04
opal_test CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T07:37:04
opal_test CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T07:37:05
opal_test CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T07:37:05
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T07:39:08
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T07:39:09
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T08:21:06
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T08:21:07
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:24:09
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:24:10
opal_test CNSIM CNSIM1 read dsuser base::exists 2026-06-01T09:24:11
opal_test CNSIM CNSIM1 read dsuser dsBase::classDS 2026-06-01T09:24:11
opal_test CNSIM CNSIM1 read dsuser dsBase::isValidDS 2026-06-01T09:24:11
opal_test CNSIM CNSIM1 read dsuser dsBase::dimDS 2026-06-01T09:24:11
opal_test CNSIM CNSIM1 read dsuser dsBase::colnamesDS 2026-06-01T09:24:11
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T09:49:44
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T09:49:45
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:24:03
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:24:05
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T10:55:52
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T10:55:54
opal_test CNSIM CNSIM1 read dsuser base::assign 2026-06-01T12:14:10
opal_test CNSIM CNSIM1 read dsuser dsBase::lsDS 2026-06-01T12:14:11
opal_test CNSIM CNSIM1 read dsuser1
opal_test CNSIM CNSIM2 read dsuser
opal_test CNSIM CNSIM2 read dsuser2
opal_test CNSIM CNSIM3 read dsuser
opal_test CNSIM CNSIM3 read dsuser3

Render and display report (HTML)

study_crate_v1 |>
  dsROCrate::report(filepath = study_crate_v1_rmd, 
                            title = "DataSHIELD Study audit",
                            render = TRUE, 
                            overwrite = TRUE)