Ontology Changelog
Changelog
Notable changes to the SOLVE-IT ontology.
[Unreleased]
Added
-
solve_it_core_shapes.ttlgainsSolveitInvestigativeActionShape, constrainingsolveit-core:appliedMitigationto IRIs. The property was declared only withrdfs:domain, so tools that build classes from SHACL shapes (the CASE-UCO SDK among them) gave a SOLVE-IT action no way to state the mitigations it applied. The values are not constrained withsh:class solveit-core:Mitigation: an action names a mitigation by its knowledge base IRI, and the data being validated does not usually contain the knowledge base, so a class constraint would reject those actions. Ansh:orofsh:class solveit-core:Mitigationandsh:nodeKind sh:IRInames the expected class for generators without changing what validates. -
solveit-observable:providesAccessTo— links asolveit-observable:DeviceInterfaceto theuco-observable:StorageMediumit gives access to. The interface classes had no facet and no object property, so nothing connected “a write-protected interface” to the disk behind it: a tool capability profile for DFT-1002 could not scope a claim to the model, serial number or capacity of the media it was tested on. The interface stays a sibling ofDevicerather than a subclass, because it is a way of reaching the medium and not the medium: the same disk can be reached write-protected on one occasion and read-write on another, and with a hardware write blocker there are two devices, which a Device-typed interface would leave ambiguous. The range isStorageMediumrather thanDevice, matching the knowledge base, where DFT-1012 and DFT-1166 take a StorageMedium and produce the interface, and keeping a write blocker out of the range.uco-observable:Diskis not a Device in UCO 1.5.0; a Disk node also typedStorageMedium, as UCO already asks, is a valid value.DeviceInterfaceShapechecks the type of the value and not the number: whether a multi-bay write blocker is one interface or one per bay is not settled. solve_it_observable_shapes.ttlgainsFileSetShapeandArtifactSetShape, constrainingsolveit-observable:hasFiletouco-observable:Fileandsolveit-observable:hasArtifacttouco-observable:ObservableObject. Both properties were declared only withrdfs:domain, so tools that build classes from SHACL shapes (the CASE-UCO SDK among them) offered no way to name a set’s members except the inheriteduco-core:object.ApplicationFilesalready constrainedhasFile;FileSetand its other subclasses now do too.-
solveit-observable:hasOperatingSystem— links auco-observable:Deviceto auco-observable:OperatingSysteminstalled on it, so a tool capability profile can scope a claim to the operating systems it was tested against. Nothing in UCO connected the two:uco-observable:operatingSystemdeclares no domain and is used onApplicationFacetfor the system an application runs on. Installed rather than running, and more than one is expected. How a condition should treat a device with several is open, and tracked in #53. solveit-tool-profile:publishedByis an object property with rangeuco-identity:Identity, not a datatype property holding the publisher’s name. The reasoning is the one that madehasCASEInputClassan object property in 0.2.1: a party held in a string literal cannot be followed, cannot be shown to be the same body as one named on another profile, and cannot be checked for a typo. “National Testing Programme” and “National Testing Programme “ are two strings and one organisation. It also removes an inconsistency —solveit-wa:evaluatedByhas always modelled the assessing party as an Identity, so the same question was answered two ways in one ontology.solve_it_tool_profile.ttlgainsToolCapabilityProfileShape, its first SHACL shape, scoped topublishedBy. A profile written against the earlier form carries a literal, and the shape reports it rather than letting it pass as an untyped value. The rest of the profile is not constrained; a full set of shapes for this module is separate work.solve_it_tool_profile.ttlimportsuco-identity1.5.0.-
Breaking. Profiles published under 0.2.5 or earlier carry the string form and no longer conform. The SOLVE-IT Workflow Builder still reads them, on the ground that dropping a publisher’s attribution is worse than reading an outdated shape, and re-emits them in the new form. SICL’s profile loader takes whatever object
publishedByhas and stringifies it, so it reads the Identity’s IRI rather than the name until its SPARQL followsuco-core:name. solve_it_tool_profile.ttldefinessolveit-tool-profile:establishedForWeakness, an object property onMitigationCapabilitywith rangesolveit-core:Weakness. A mitigation usually addresses many weaknesses — DFM-1054 addresses eighteen — so a capability that names only its mitigation is read as covering all of them, including the ones the publisher never tested. Naming weaknesses records what a test campaign actually established rather than what the mitigation could in principle address.solve_it_tool_profile.ttldefinessolveit-tool-profile:supportingCitation, an object property onMitigationCapabilitywith rangesolveit-core:Citation, for the report or study a capability rests on. The profile mints its own Citation carryingcitationPlaintextorcitationBibtexand omittingcitationID, so citing a test report does not require it to be registered in the DFCite series. That idiom differs from the comment onsolveit-core:Citation, which describes a registry reference reached from a Technique, Weakness or Mitigation, and it is documented onsupportingCitationwhere it is introduced.solveit-core:hasReferencewas not widened to carry this, because widening a core term to serve one module puts the change in the module that did not need it.solve_it_tool_profile.ttlgainsMitigationCapabilityShape, its second SHACL shape, constraining node kind and class on both new properties.establishedForWeaknesscarries no minimum at violation severity: every profile published before the term existed declares no weakness scope, and a required minimum would report all of them as invalid. A capability declaring no scope produces onesh:Inforesult instead — a statement of what the profile does not say, not a fault in it. pySHACL countssh:Inforesults towards non-conformance unless it is run with--allow-info, so that flag is part of running these shapes rather than a convenience.-
solve_it_examples/tool_profile_examples.ttldeclares DFW-1086 and DFW-1087 alongside DFW-1085, and the testing programme’s capability now establishes DFM-1054 for two of the three and cites the test report that established it. The vendor’s capability still declares no scope, so the file also carries the form every profile published to date takes. solve_it_weakness_assessment.ttldefinessolveit-wa:scoringScheme, a datatype property onWeaknessEvaluationSetwith rangexsd:stringand the valuesfi,fmeaandfmea6. The term was already being read and written by SOLVE-IT tooling but was defined nowhere, so it was being asserted into this namespace without the namespace defining it. Without it a consumer cannot tell a 3 meaning “high” on a three-point scale from a 3 meaning “moderate” on a six-point one, so the same integer describes two different risks.WeaknessEvaluationSetShapeconstrains it to those three values.WeaknessEvaluationShapeadmits the ratings the six-point FMEA scheme produces. It previously bounded every factor at 3,liImpactScoreat 9 andrpnScoreat 27, which are the three-point maxima; a six-point assessment reaches 6, 36 and 216 and could not validate at all. The bounds are now 6, 36 and 216. Existing three-point data is unaffected, since its range is a subset of the new one.-
solve_it_weakness_assessment.ttldefinessolveit-wa:ThreePointRatingShapeandsolveit-wa:SixPointRatingShape, which carry the per-scheme bounds. The widenedWeaknessEvaluationShapecan no longer reject a 5 in a set declaring a three-point scheme, and SHACL Core cannot make one node’s constraint depend on a value held by another — the scheme is declared on the set, the ratings sit on the evaluations. Neither shape carriessh:targetClass, so neither fires on its own; a consumer that has read the scheme applies the matching one explicitly. solve_it_analysis.ttlno longer definessolveit-analysis:supportedByorsolveit-analysis:contradictedBy. Both were object properties onHypothesiswith rangeuco-observable:ObservableObject, linking a hypothesis to the artifacts that supported or contradicted it. No replacement term is defined in their place.- The
rdfs:commentonsolveit-analysis:HypothesisedUserAccountno longer points atsupportedBy. - The
rdfs:commentonsolveit-analysis:Hypothesisreads “A statement that is either true or false, the truth of which is uncertain.” The previous wording described a hypothesis as something that may be supported or contradicted by observable artifacts, which the ontology no longer provides any way to state.
Fixed
solve_it_examples/sqlite_examples.ttlno longer usessolveit-analysis:supportedBy, which was removed. The HypothesisedRecord example (#34) was written before the removal and merged after it, so the example validation failed onmainand stopped the documentation build. The two triples naming page 2 as the grounds are gone; the comment above the example still explains why each hypothesis is reasonable. Therdfs:commentonHypothesisedRelationship,HypothesisedRecordandHypothesisedTableAttributionno longer tells a reader to use the removed terms.- The DFT-1042 example in
solve_it_examples/core_classes_examples.ttlcarries the technique’s current name, “Verify hash of copied data matches the hash of the data read from source device”. The knowledge base renamed it, andvalidate_examples.pychecks example labels against the live knowledge base, so the old name failed the docs workflow for every change. The same name insolve_it_examples/README.mdis updated to match.
[0.2.5] — 2026-08-25
solve_it_core.ttldefinessolveit-core:Citation, withcitationID,citationPlaintextandcitationBibtex. The knowledge base has published 158 citations as resources typedsolveit-core:Citationfor some time, but the ontology defined no citation term at all, so all four were being asserted into the ontology’s namespace without being defined in it.solve_it_core.ttldefinessolveit-core:objectiveIDandsolveit-core:sortOrder, both onObjective, and both used by the knowledge base on all 24 objectives.techniqueID,weaknessIDandmitigationIDwere already declared, soobjectiveIDwas the one identifier property missing.sortOrderis anxsd:integergiving the position of an objective in investigation order.solveit-core:hasReferenceis anowl:ObjectPropertywith rangesolveit-core:Citation, in place of anowl:DatatypePropertywith rangexsd:string. The knowledge base gives it an IRI on all 241 statements, which a datatype property cannot take, so the published data was not valid OWL DL. The domain is unchanged: the union of Technique, Weakness and Mitigation still matches the knowledge base exactly, at 126, 62 and 53 statements.- The examples reference citations by IRI, as
solveit-core:hasReference solveit-data:citationDFCite-1107, in place of the string"DFCite-1107". All 18 are incore_classes_examples.ttland every identifier already agreed with the knowledge base, so only the form changed. scripts/validate_kb_conformance.pychecks the generated knowledge base against the ontology, and fails if the knowledge base uses a SOLVE-IT ontology term that no ontology file defines, or gives a datatype property an IRI or an object property a literal. Run against the ontology as it stood before this release it reports all seven faults above; nothing in the repository reported any of them.- The conformance check runs in
validate-ontology.ymlandvalidate-and-build-docs.yml, and ingenerate-knowledge-base.ymlbefore that job commits, so a knowledge base using an undefined term is not published. The last of those is the one that matters: that job commits withGITHUB_TOKEN, and GitHub does not start workflow runs for pushes made with that token, so a push trigger would never have seen a knowledge base update. - The gap these checks close is that
reporting_scripts/generate_rdf_from_kb.pyin the solve-it repository mints terms through rdflibNamespaceobjects, which build an IRI by string concatenation and cannot fail, and it never reads the ontology.validate_ontology.pydoes not load the knowledge base, andvalidate_examples.pyandvalidate_example_io.pyload it only as the reference to check the examples against, so the knowledge base itself was never checked by anything.
[0.2.4] — 2026-08-25
validate-and-build-docs.ymlnow runsontospy gendocsagainst a staging directory holding only the root-levelsolve_it_*.ttlfiles, in place of the repository root.scripts/build_docs_local.shis changed to match.- ontospy recurses into subdirectories, so pointing it at the repository root
also read
solve_it_examples/. Since the UCO 1.5.0 metaclass change the examples declare techniques as classes, witha owl:Class , solveit-core:Technique, so ontospy rendered a class page for each one and listed it in the class index. Tensolveit-data:techniqueDFT-*entries were published as part of the ontology’s own vocabulary, all ten declared insolve_it_examples/core_classes_examples.ttl: DFT-1002, 1005, 1042, 1049, 1052, 1060, and 1122 to 1125. Which ten appeared depended only on which techniques that file declares. A technique the examples use without declaring it, naming it only as therdf:typeof an action instance, produced no page: DFT-1121, DFT-1182 and DFT-1183 are used that way and did not appear. - Technique entries are knowledge base data, published at
data.solveit-df.org. The ontology definessolveit-core:Technique, and the individual entries are instances of it. The examples themselves remain documented, bygenerate_examples_page.py. - The two shapes files are still read by the documentation build, so
sh:NodeShapecontinues to appear in the class index. generate_iri_redirects.pynow reads the ontology with rdflib in place of regular expressions, takes each module name from the entity’s IRI rather than by splitting its prefix, and keys entities on module and local name together rather than on local name alone. It generates 260 redirect folders, up from 226.- The 34 IRIs that gained a redirect were returning 404 on the published site.
Thirteen are
tool-profileterms and nineteen areweakness-assessmentterms: the parser tested for the three prefixessolveit-core:,solveit-analysis:andsolveit-observable:, so the two modules added since it was written were skipped in full, and neither module had any resolvable IRI. The remaining two aresolveit-observable:hasArtifactandsolveit-observable:hasFile, which collided with thesolveit-analysis:properties of the same local name. Both pairs are distinct properties with different domains,ForensicToolTagBasedReportagainstArtifactSetandFileSet, and the redirect path already separates them by module, but keying on the local name discarded one of each pair. Which one survived depended on the orderPath.globreturned the files in, so it could change between runs with no edit to the ontology. generate_iri_redirects.pyfails, and writes nothing, if an entity’s namespace has no declaredsolveit-prefix or if a redirect would point at a page that does not exist. The module name and the documentation filename come from different places: the folder path comes from the IRI, sosolveit-wa:hasEvaluationis served at/solveit/weakness-assessment/hasEvaluation, while Ontospy names the page after the declared prefix,prop-solveit-wahasevaluation.html. A redirect built from the wrong one of those is a 404 that appears only when someone dereferences the IRI.- The 226 redirects that already existed are byte-identical after the change.
- The keyword search examples in
core_classes_examples.ttldeclarehasCASEOutputClass solveit-observable:KeywordSearchResultSetfor DFT-1049, DFT-1122, DFT-1123 and DFT-1125, in place ofsolveit-observable:KeywordSearchResult. The knowledge base had been updated to the set-valued class, socheck_kb_driftinvalidate_examples.pyreported the four as drifted and the validation step failed ahead of the documentation build. DFT-1124 already declared the set. The example actions for these techniques already produce aKeywordSearchResultSet, so the declarations were the part that was behind.
[0.2.3] — 2026-08-20
validate-against-case-1.5.0.ymlnow runs automatically. It previously ran only when started by hand from the Actions tab, and had not been run since it was written on 5 August. It is now triggered by pushes tomainthat touch a TTL file, by pull requests touching the same paths, and bygenerate-knowledge-base.ymlcalling it directly.- The call from
generate-knowledge-base.ymlis made only on the runs where that job committed a rebuilt knowledge base, which is a small proportion of its hourly runs. A direct call is used in place of the push trigger because that job commits usingGITHUB_TOKEN, and GitHub does not start further workflow runs for pushes made with that token. validate-against-case-1.5.0.ymlnow confirms that the SOLVE-IT shapes are in the graph it validates against before reporting a pass. The shapes reachcase_validatebecause the two shapes files are matched by thesolve_it_*.ttlpattern used to build the merged ontology graph. Renaming a shapes file, or narrowing that pattern, would remove all 13 SOLVE-IT shapes from the graph, and every run would continue to report success. A technique that breaksTechniqueIOTermShapeis now validated first, and the job fails if it is accepted.- The merged CASE, UCO and SOLVE-IT graph used by
validate-against-case-1.5.0.ymlis cached, keyed on the CASE release tag and a hash of the local ontology files, so that a run does not check out CASE with its UCO submodule and reparse 32 files each time. validate-and-build-docs.ymlchecks out withfetch-depth: 2. The step that decides whether to bump the patch version tests whetherVERSIONchanged by runninggit diff HEAD~1, andactions/checkoutdefaults tofetch-depth: 1, soHEAD~1was not present in the runner’s clone. The command failed, and the step reported “not changed” whatever the commit contained, so a version set by hand was always overwritten by the automatic patch bump.- The 0.2.1 section is titled 0.2.1 rather than the 0.2.0 that was set in
VERSIONfor the UCO 1.5.0 metaclass change, because the fault above meant 0.2.0 was never stamped into the ontology files and never published.
[0.2.2] — 2026-08-20
hasCASEInputClassandhasCASEOutputClassno longer declarerdfs:range owl:Class. A technique’s declared input or output is usually a class, but where the technique consumes or produces a single value rather than an object it is a property, for examplecase-investigation:exhibitNumberoruco-observable:filePath. 42 of the 173 terms the knowledge base references are properties. No singlerdfs:rangeadmits both classes and properties without also admitting everything else, so the restriction is now stated in SHACL rather than in OWL.- Added
TechniqueIOTermShapetosolve_it_core_shapes.ttl. Every term named as a technique input or output must be declared anowl:Class,owl:DatatypePropertyorowl:ObjectProperty. This replaces therdfs:rangeremoved above. - Added
TechniqueIOTermConsistencyShapetosolve_it_core_shapes.ttl. A term must not be declared as more than one of those three kinds. This detects a SOLVE-IT declaration that contradicts the one CASE or UCO gives the same term, whichTechniqueIOTermShapecannot do, because that shape is satisfied by whatever declaration the knowledge base itself supplies. It only reports a violation when CASE and UCO are loaded alongside the data being validated. Run against the knowledge base as published before this change it reports 56 violations across the 42 property terms, and none against the output of the corrected generator. -
The two property names still contain the word “Class” although they now accept properties. They are expected to become
hasInputandhasOutputshortly, alongside the corresponding change in the knowledge base, so they are left unchanged here in order that the rename happens once. scripts/validate_examples.pynow requires knowledge base entities referenced in the examples to be written in thesolveit-data:namespace. An example that writes:techniqueDFT-1002against its own default prefix defines a separate entity in the examples namespace rather than referring to the catalogue entry of that name. Such a file is internally consistent and validates cleanly while describing entities that exist nowhere else, which is how the three mis-namespaced references insolve_it_examples/weakness_assessment_examples.ttlwent unnoticed.scripts/validate_examples.pynow compares the inline copies of catalogue entries held in the examples against the knowledge base. Examples restate techniques, weaknesses and mitigations so that a file can be read without opening the knowledge base, and those restatements can fall out of step with it. A value the example leaves out is accepted, because stating two of a technique’s five input classes is a partial restatement rather than a contradiction. A value the example asserts that the knowledge base does not hold is reported as an error.scripts/validate_examples.pynow followsrdfs:subClassOfwhen checking the input and output types of a performed action. A technique that declaresTimelineas its input is satisfied by aSortedTimeline, which is a subclass of it. The previous check compared the two sets of types directly and reported a mismatch in that case.
[0.2.1] — 2026-08-19
Techniquenow subclassesuco-action:Techniquerather thancase-investigation:InvestigativeAction, following the metaclass model introduced in UCO 1.5.0. A technique is a class; a performed action states which technique it implements byrdf:type, not by a property. The previous axiom sat on the metaclass and so made every catalogue entry a performed action.SolveitInvestigativeActionretained, and is now the parent of every technique class. It remains the anchor for occurrence-level properties, soappliedMitigationis unchanged — its domain is satisfied by inference.usedTechniquemarkedowl:deprecated. Retained so existing data parses.hasCASEInputClassandhasCASEOutputClasschanged from datatype properties with rangexsd:anyURIto object properties with rangeowl:Class. A class IRI held in a string literal cannot be followed by a reasoner, walked by a SPARQL property path, or checked for a typo.- All UCO and CASE imports moved from 1.4.0 to 1.5.0 across 9 files. A partial
bump does not work:
uco-action1.5.0 importsuco-core1.5.0, which would put two versionIRIs of the same ontology in one import closure. - SHACL: retired
SolveitInvestigativeActionShape, which required at least oneusedTechnique; under the metaclass model there is no violating state left to detect. AddedTechniqueShape, checking what OWL cannot express — that a technique is also declaredowl:Classand carries anrdfs:subClassOf. - Example actions migrated from
usedTechniquetordf:typeagainst the technique class, across six files. validate_examples.pynow loads the generated knowledge base (docs/data/solve-it-kb.ttl). The technique classes the examples type their actions with are defined there, not in the ontology files, so without it the examples could not be resolved against a complete schema and every domain check against an action reported a violation that was not real.- Retyped the keyword indexing example from
techniqueDFT-1126(Keyword search (live) (physical)) totechniqueDFT-1121(Index a data source for keyword searching). The action builds an index from aFileSetand anArtifactSetand produces aKeywordIndex, which is what DFT-1121 declares; it was typed as a search. - Qualified the technique and weaknesses in
weakness_assessment_examples.ttlwith thesolveit-data:prefix. They were written against the file’s default prefix, so they resolved into the examples namespace and described look-alikes rather than the catalogue entries the evaluations scored.
[0.1.10] — 2026-08-11
- Added
rowiddata property toSQLiteRecord. - Clarified comments on
fieldTypeandhasBlobContentin the SQLite module.
Versions up to 0.1.9 were reconstructed retrospectively from git history on
2026-08-11. Patch versions are assigned automatically by CI on push (see
scripts/sync_version.py), so each version is dated by the commit that stamped
it. Patch versions containing only automated rebuilds and no ontology changes
(0.0.8, 0.1.1) are omitted.
[0.1.9] — 2026-07-10
- Added
HypothesisedUserAccountto the analysis module. - README: documented that external consumers (e.g. the KB build) need updating when new module files are added.
[0.1.8] — 2026-07-02
- Added
HypothesisSetto support SOLVE-IT technique modelling.
[0.1.7] — 2026-06-25
- Added
VirtualizedDeviceandVirtualizedComputer.
[0.1.6] — 2026-06-24
- Added
VideoFileandAudioFile.
[0.1.5] — 2026-06-24
- Added
HashSet(withHashSetEntryandHashVerificationResult) plus example. - Added IDs to the timeline sorting example.
[0.1.4] — 2026-03-30
- Added sorted timeline concept (
SortedTimeline,SortedTimelineEntry) and a draft example using the SOLVE-IT timeline techniques.
[0.1.3] — 2026-03-23
- Added
TimestampOffset.
[0.1.2] — 2026-03-21
- Added
SmartHomeAppFiles.
[0.1.0] — 2026-03-20
- Renamed
PerformedTechniquetoSolveitInvestigativeAction. - Restructured weakness classification to support the new weakness formats.
- Added detail to keyword classes and added search examples.
- Improved examples and updated them to the new naming scheme.
- Added input/output class validation for examples (
validate_example_io.py).
[0.0.7] — 2026-03-17
- Added
GamingAppFiles.
[0.0.6] — 2026-03-09
- Added weakness assessment module (
solve_it_weakness_assessment.ttl) with risk scoring, plus examples. - Added application file set classes (
BrowserAppFiles,ChatAppFiles,EmailAppFiles,PhotosAppFiles, and others). - Added hypothesised event subclasses to the analysis module
(
HypothesisedWebSearch,HypothesisedCommunication, and others).
[0.0.5] — 2026-03-03
- Updated
FileSystemExtraction.
[0.0.4] — 2026-03-03
- Added mobile acquisition types:
iOSDeviceGeneratedBackup,AndroidDeviceGeneratedBackup,AppleUnifiedLogArchive,ContentQueryData.
[0.0.3] — 2026-03-03
- Docs tooling: GitHub repository link added to generated documentation pages.
[0.0.2] — 2026-03-03
- Added SQLite module (
solve_it_sqlite.ttl) with classes and examples. - Added hypothesis stub classes and
hypothesisedDateTimeproperty. - Added CASE input class support (
hasCaseInputClass). - Added
FileSetandFilteredFileSet; refinedRedactedFileSet; added aPrioritizedDeviceSetexample. - Acquisition/interface updates: added
ReadWriteDeviceInterface, reworded read-only interface; accommodated screenshots and clock offsets as acquisitions; SHACL fix forClockOffsetMeasurement. - Split forensic image containers into subclasses by contents
(
PhysicalImageContainer,LogicalImageContainer). - Added
BitstreamRandomAccessedandLiveOSDeviceInterface. - Added
BrowserCacheData. Mitigationnow subclassesInvestigativeAction.- Reworded
usedTechnique(potentially breaking). - Accommodated time ranges in
TimelineEntry. - Tooling: validation scripts run as a GitHub Action; automatic version sync.
[0.0.1] — 2026-02-20
First versioned release: added the VERSION file, version bump/sync scripts,
and documentation tidy-up. The ontology content at this point comprised the
pre-versioning development below.
Pre-versioning (2025-12-17 – 2026-02-20)
- Initial ontology structure: core classes (
Objective,Technique,Weakness,Mitigation) aligned to CASE/UCO, with observables and analysis split into separate module files. - Added
PerformedTechniquelinking performed actions to techniques and applied mitigations;Techniquechanged to subclassInvestigativeActionrather thanUcoObject. - Added tool profile module (
ToolCapabilityProfile,MitigationCapability,SolveItAwareInstrument). - Many observable classes:
Timeline/TimelineEntry,ImplicitTimingInformation,KeywordSearchResult,KeywordIndex,UnlockPattern,DecryptionKey,RedactedFileSet/RedactedArtifactSet,NetworkPacketCapture,ForensicToolTagBasedReport,ClockOffset,HTTPResponseHeader,DateTimeStamp,ApplicationFiles, screenshot acquisition types,AcquisitionRecordFile. - Added
DataAcquisitionand subclasses with acquisition error records. - Updated CASE/UCO alignment from 1.3 to 1.4.0.
- Infrastructure: GitHub Pages documentation at
ontology.solveit-df.orgwith IRI redirects; daily knowledge base RDF endpoint; MIT licence.