From 9d5b6256fae666f48eb1edb2dcec1c48bc583cfb Mon Sep 17 00:00:00 2001 From: Cory Hall Date: Wed, 22 Oct 2025 11:23:20 -0400 Subject: [PATCH 1/4] Add investigation:Technician role class Adds investigation:Technician as a new role class to the CASE investigation ontology, addressing Issue #184. A technician is a forensics role focused on technical tasks during investigations, such as evidence collection, preservation, processing, initial analysis, and repair. Changes: - Added investigation:Technician class definition to investigation.ttl - Created comprehensive test example (technician_role_PASS.json) demonstrating Identity-role-performer pattern with temporal tracking - Updated test suite (Makefile and test_validation.py) - Updated ChangeLog The implementation follows the established pattern used by other role classes (Attorney, Examiner, Investigator, Subject) and maintains backward compatibility. Tests demonstrate: - Technician role instances with appointment dates (startTime) - Identity linked to Technician role via uco-core:role - Technician role as performer of InvestigativeAction - Integration with Investigation, File, and ProvenanceRecord All SHACL validation tests pass. Closes #184 --- ChangeLog | 3 ++ ontology/investigation/investigation.ttl | 11 ++++ tests/examples/Makefile | 6 ++- tests/examples/technician_role_PASS.json | 64 ++++++++++++++++++++++++ tests/examples/test_validation.py | 7 +++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 tests/examples/technician_role_PASS.json diff --git a/ChangeLog b/ChangeLog index 053bd62..d09ff3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2025-10-22 + * Issue 184: Add investigation:Technician role class + 2025-03-18 * (7ecdaf4) UCO Issue 629: Revise vocabulary pattern diff --git a/ontology/investigation/investigation.ttl b/ontology/investigation/investigation.ttl index a572ba4..faf4b99 100644 --- a/ontology/investigation/investigation.ttl +++ b/ontology/investigation/investigation.ttl @@ -235,6 +235,17 @@ investigation:SubjectActionLifecycle sh:targetClass investigation:SubjectActionLifecycle ; . +investigation:Technician + a + owl:Class , + sh:NodeShape + ; + rdfs:subClassOf uco-role:Role ; + rdfs:label "Technician"@en ; + rdfs:comment "Technician is a role involved in performing technical tasks during investigations, such as evidence collection, preservation, processing, initial analysis, and repair."@en ; + sh:targetClass investigation:Technician ; + . + investigation:VictimActionLifecycle a owl:Class , diff --git a/tests/examples/Makefile b/tests/examples/Makefile index f79c2a5..daa1e81 100644 --- a/tests/examples/Makefile +++ b/tests/examples/Makefile @@ -22,7 +22,8 @@ tests_srcdir := $(top_srcdir)/tests all: \ investigative_action_PASS_validation.ttl \ - investigative_action_XFAIL_validation.ttl + investigative_action_XFAIL_validation.ttl \ + technician_role_PASS_validation.ttl .PRECIOUS: \ %_validation.ttl @@ -63,7 +64,8 @@ all: \ check: \ investigative_action_PASS_validation.ttl \ - investigative_action_XFAIL_validation.ttl + investigative_action_XFAIL_validation.ttl \ + technician_role_PASS_validation.ttl source $(top_srcdir)/venv/bin/activate \ && pytest \ --log-level=DEBUG diff --git a/tests/examples/technician_role_PASS.json b/tests/examples/technician_role_PASS.json new file mode 100644 index 0000000..0952a71 --- /dev/null +++ b/tests/examples/technician_role_PASS.json @@ -0,0 +1,64 @@ +{ + "@context": { + "kb": "http://example.org/kb/", + "case-investigation": "https://ontology.caseontology.org/case/investigation/", + "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", + "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", + "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", + "@type": "uco-core:Identity", + "uco-core:name": "Forensic Technician Williams", + "uco-core:role": { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + } + }, + { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a", + "@type": "case-investigation:Technician", + "uco-core:startTime": { + "@type": "xsd:dateTime", + "@value": "2024-01-15T09:00:00Z" + } + }, + { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f", + "@type": "uco-observable:File", + "uco-core:description": "Forensic disk image of evidence laptop", + "uco-core:hasFacet": { + "@id": "kb:disk-image-facet-a3c9f7e1-d5b2-4a8e-9c3f-7e1a5d9b2c4f", + "@type": "uco-observable:FileFacet", + "uco-observable:fileName": "evidence-laptop-001.dd", + "uco-observable:sizeInBytes": 512000000000 + } + }, + { + "@id": "kb:disk-imaging-action-5d7a3e9f-c2b4-4f8a-9e3d-6c1b5a8f7e2d", + "@type": "case-investigation:InvestigativeAction", + "uco-core:name": "Disk imaging of evidence laptop", + "uco-action:performer": { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + }, + "uco-action:result": [ + { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" + }, + { + "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f" + } + ] + }, + { + "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f", + "@type": "case-investigation:ProvenanceRecord", + "case-investigation:exhibitNumber": "2024-001-E1", + "case-investigation:rootExhibitNumber": "2024-001-E1", + "uco-core:object": { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" + } + } + ] +} diff --git a/tests/examples/test_validation.py b/tests/examples/test_validation.py index d873012..f496979 100644 --- a/tests/examples/test_validation.py +++ b/tests/examples/test_validation.py @@ -128,3 +128,10 @@ def test_investigative_action_XFAIL_validation() -> None: str(NS_CASE_INVESTIGATION.rootExhibitNumber) } ) + +def test_technician_role_PASS_validation() -> None: + """ + Confirm the Technician role PASS instance data passes validation. + """ + g = load_validation_graph("technician_role_PASS_validation.ttl", True) + assert isinstance(g, rdflib.Graph) From 1fce2fb878faf7e2fdf903ffcba3680615217d14 Mon Sep 17 00:00:00 2001 From: Alex Nelsin Date: Tue, 2 Dec 2025 18:17:13 -0500 Subject: [PATCH 2/4] Change line endings No effects were observed on Make-managed files. Signed-off-by: Alex Nelsin --- tests/examples/technician_role_PASS.json | 128 +++++++++++------------ 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/examples/technician_role_PASS.json b/tests/examples/technician_role_PASS.json index 0952a71..e6940d1 100644 --- a/tests/examples/technician_role_PASS.json +++ b/tests/examples/technician_role_PASS.json @@ -1,64 +1,64 @@ -{ - "@context": { - "kb": "http://example.org/kb/", - "case-investigation": "https://ontology.caseontology.org/case/investigation/", - "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", - "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", - "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", - "xsd": "http://www.w3.org/2001/XMLSchema#" - }, - "@graph": [ - { - "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", - "@type": "uco-core:Identity", - "uco-core:name": "Forensic Technician Williams", - "uco-core:role": { - "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" - } - }, - { - "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a", - "@type": "case-investigation:Technician", - "uco-core:startTime": { - "@type": "xsd:dateTime", - "@value": "2024-01-15T09:00:00Z" - } - }, - { - "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f", - "@type": "uco-observable:File", - "uco-core:description": "Forensic disk image of evidence laptop", - "uco-core:hasFacet": { - "@id": "kb:disk-image-facet-a3c9f7e1-d5b2-4a8e-9c3f-7e1a5d9b2c4f", - "@type": "uco-observable:FileFacet", - "uco-observable:fileName": "evidence-laptop-001.dd", - "uco-observable:sizeInBytes": 512000000000 - } - }, - { - "@id": "kb:disk-imaging-action-5d7a3e9f-c2b4-4f8a-9e3d-6c1b5a8f7e2d", - "@type": "case-investigation:InvestigativeAction", - "uco-core:name": "Disk imaging of evidence laptop", - "uco-action:performer": { - "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" - }, - "uco-action:result": [ - { - "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" - }, - { - "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f" - } - ] - }, - { - "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f", - "@type": "case-investigation:ProvenanceRecord", - "case-investigation:exhibitNumber": "2024-001-E1", - "case-investigation:rootExhibitNumber": "2024-001-E1", - "uco-core:object": { - "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" - } - } - ] -} +{ + "@context": { + "kb": "http://example.org/kb/", + "case-investigation": "https://ontology.caseontology.org/case/investigation/", + "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", + "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", + "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", + "@type": "uco-core:Identity", + "uco-core:name": "Forensic Technician Williams", + "uco-core:role": { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + } + }, + { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a", + "@type": "case-investigation:Technician", + "uco-core:startTime": { + "@type": "xsd:dateTime", + "@value": "2024-01-15T09:00:00Z" + } + }, + { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f", + "@type": "uco-observable:File", + "uco-core:description": "Forensic disk image of evidence laptop", + "uco-core:hasFacet": { + "@id": "kb:disk-image-facet-a3c9f7e1-d5b2-4a8e-9c3f-7e1a5d9b2c4f", + "@type": "uco-observable:FileFacet", + "uco-observable:fileName": "evidence-laptop-001.dd", + "uco-observable:sizeInBytes": 512000000000 + } + }, + { + "@id": "kb:disk-imaging-action-5d7a3e9f-c2b4-4f8a-9e3d-6c1b5a8f7e2d", + "@type": "case-investigation:InvestigativeAction", + "uco-core:name": "Disk imaging of evidence laptop", + "uco-action:performer": { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + }, + "uco-action:result": [ + { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" + }, + { + "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f" + } + ] + }, + { + "@id": "kb:provenance-record-e9f5c1a7-d4b8-4a6e-9c2f-3e5d7a9b1c4f", + "@type": "case-investigation:ProvenanceRecord", + "case-investigation:exhibitNumber": "2024-001-E1", + "case-investigation:rootExhibitNumber": "2024-001-E1", + "uco-core:object": { + "@id": "kb:disk-image-3f8a2c7d-b1e9-4d3c-a5f7-1b2e4a9c8d6f" + } + } + ] +} From 288aae75c56a08cc10309cafeb8f8525f1351e8b Mon Sep 17 00:00:00 2001 From: Alex Nelsin Date: Tue, 2 Dec 2025 18:20:10 -0500 Subject: [PATCH 3/4] Regenerate Make-managed files References: * https://github.com/casework/CASE/issues/184 Signed-off-by: Alex Nelsin --- tests/examples/technician_role_PASS_validation.ttl | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/examples/technician_role_PASS_validation.ttl diff --git a/tests/examples/technician_role_PASS_validation.ttl b/tests/examples/technician_role_PASS_validation.ttl new file mode 100644 index 0000000..33496ff --- /dev/null +++ b/tests/examples/technician_role_PASS_validation.ttl @@ -0,0 +1,11 @@ +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix sh: . +@prefix xsd: . + +[] + a sh:ValidationReport ; + sh:conforms "true"^^xsd:boolean ; + . + From bed10f76e7abec0450500d941590dac35463d6eb Mon Sep 17 00:00:00 2001 From: Alex Nelsin Date: Tue, 2 Dec 2025 18:33:40 -0500 Subject: [PATCH 4/4] Revise Technician example to have person be the action-performer Note this patch does not tie the role to the action, nor does it define an investigation to tie the action, person, role, relationship, etc., together, due to needing to address broader design issues pertaining to `uco-role:Role`, some of which are under exploration in CASE-Examples Issue 155. This patch also fixes a typo'd concept - `uco-core:Identity` was used instead of `uco-identity:Identity`. This was not revised to `uco-identity:Person` in light of discussion going on in UCO Issue 652. No effects were observed on Make-managed files. References: * https://github.com/casework/CASE/issues/184 * https://github.com/casework/CASE-Examples/issues/155 * https://github.com/ucoProject/UCO/issues/652 Signed-off-by: Alex Nelsin --- tests/examples/technician_role_PASS.json | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/examples/technician_role_PASS.json b/tests/examples/technician_role_PASS.json index e6940d1..b9c0c6e 100644 --- a/tests/examples/technician_role_PASS.json +++ b/tests/examples/technician_role_PASS.json @@ -4,13 +4,14 @@ "case-investigation": "https://ontology.caseontology.org/case/investigation/", "uco-action": "https://ontology.unifiedcyberontology.org/uco/action/", "uco-core": "https://ontology.unifiedcyberontology.org/uco/core/", + "uco-identity": "https://ontology.unifiedcyberontology.org/uco/identity/", "uco-observable": "https://ontology.unifiedcyberontology.org/uco/observable/", "xsd": "http://www.w3.org/2001/XMLSchema#" }, "@graph": [ { "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", - "@type": "uco-core:Identity", + "@type": "uco-identity:Identity", "uco-core:name": "Forensic Technician Williams", "uco-core:role": { "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" @@ -18,7 +19,19 @@ }, { "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a", - "@type": "case-investigation:Technician", + "@type": "case-investigation:Technician" + }, + { + "@id": "kb:relationship-13b1d06d-1697-4085-bd1c-88d1df713b19", + "@type": "uco-core:Relationship", + "uco-core:kindOfRelationship": "Has_Role", + "uco-core:isDirectional": true, + "uco-core:source": { + "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d" + }, + "uco-core:target": { + "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + }, "uco-core:startTime": { "@type": "xsd:dateTime", "@value": "2024-01-15T09:00:00Z" @@ -40,7 +53,7 @@ "@type": "case-investigation:InvestigativeAction", "uco-core:name": "Disk imaging of evidence laptop", "uco-action:performer": { - "@id": "kb:technician-role-c8d9f2e1-a4b7-4c3e-8f5d-6a1e9b2c7f4a" + "@id": "kb:technician-identity-9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d" }, "uco-action:result": [ {