Changelog

Notable changes to the SOLVE-IT ontology.

[Unreleased]

Added

  • solve_it_core_shapes.ttl gains SolveitInvestigativeActionShape, constraining solveit-core:appliedMitigation to IRIs. The property was declared only with rdfs: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 with sh: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. An sh:or of sh:class solveit-core:Mitigation and sh:nodeKind sh:IRI names the expected class for generators without changing what validates.

  • solveit-observable:providesAccessTo — links a solveit-observable:DeviceInterface to the uco-observable:StorageMedium it 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 of Device rather 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 is StorageMedium rather than Device, 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:Disk is not a Device in UCO 1.5.0; a Disk node also typed StorageMedium, as UCO already asks, is a valid value. DeviceInterfaceShape checks 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.ttl gains FileSetShape and ArtifactSetShape, constraining solveit-observable:hasFile to uco-observable:File and solveit-observable:hasArtifact to uco-observable:ObservableObject. Both properties were declared only with rdfs: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 inherited uco-core:object. ApplicationFiles already constrained hasFile; FileSet and its other subclasses now do too.
  • solveit-observable:hasOperatingSystem — links a uco-observable:Device to a uco-observable:OperatingSystem installed 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:operatingSystem declares no domain and is used on ApplicationFacet for 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:publishedBy is an object property with range uco-identity:Identity, not a datatype property holding the publisher’s name. The reasoning is the one that made hasCASEInputClass an 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:evaluatedBy has always modelled the assessing party as an Identity, so the same question was answered two ways in one ontology.
  • solve_it_tool_profile.ttl gains ToolCapabilityProfileShape, its first SHACL shape, scoped to publishedBy. 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.ttl imports uco-identity 1.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 publishedBy has and stringifies it, so it reads the Identity’s IRI rather than the name until its SPARQL follows uco-core:name.

  • solve_it_tool_profile.ttl defines solveit-tool-profile:establishedForWeakness, an object property on MitigationCapability with range solveit-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.ttl defines solveit-tool-profile:supportingCitation, an object property on MitigationCapability with range solveit-core:Citation, for the report or study a capability rests on. The profile mints its own Citation carrying citationPlaintext or citationBibtex and omitting citationID, so citing a test report does not require it to be registered in the DFCite series. That idiom differs from the comment on solveit-core:Citation, which describes a registry reference reached from a Technique, Weakness or Mitigation, and it is documented on supportingCitation where it is introduced. solveit-core:hasReference was 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.ttl gains MitigationCapabilityShape, its second SHACL shape, constraining node kind and class on both new properties. establishedForWeakness carries 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 one sh:Info result instead — a statement of what the profile does not say, not a fault in it. pySHACL counts sh:Info results 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.ttl declares 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.ttl defines solveit-wa:scoringScheme, a datatype property on WeaknessEvaluationSet with range xsd:string and the values fi, fmea and fmea6. 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. WeaknessEvaluationSetShape constrains it to those three values.
  • WeaknessEvaluationShape admits the ratings the six-point FMEA scheme produces. It previously bounded every factor at 3, liImpactScore at 9 and rpnScore at 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.ttl defines solveit-wa:ThreePointRatingShape and solveit-wa:SixPointRatingShape, which carry the per-scheme bounds. The widened WeaknessEvaluationShape can 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 carries sh:targetClass, so neither fires on its own; a consumer that has read the scheme applies the matching one explicitly.

  • solve_it_analysis.ttl no longer defines solveit-analysis:supportedBy or solveit-analysis:contradictedBy. Both were object properties on Hypothesis with range uco-observable:ObservableObject, linking a hypothesis to the artifacts that supported or contradicted it. No replacement term is defined in their place.
  • The rdfs:comment on solveit-analysis:HypothesisedUserAccount no longer points at supportedBy.
  • The rdfs:comment on solveit-analysis:Hypothesis reads “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.ttl no longer uses solveit-analysis:supportedBy, which was removed. The HypothesisedRecord example (#34) was written before the removal and merged after it, so the example validation failed on main and 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. The rdfs:comment on HypothesisedRelationship, HypothesisedRecord and HypothesisedTableAttribution no longer tells a reader to use the removed terms.
  • The DFT-1042 example in solve_it_examples/core_classes_examples.ttl carries 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, and validate_examples.py checks example labels against the live knowledge base, so the old name failed the docs workflow for every change. The same name in solve_it_examples/README.md is updated to match.

[0.2.5] — 2026-08-25

  • solve_it_core.ttl defines solveit-core:Citation, with citationID, citationPlaintext and citationBibtex. The knowledge base has published 158 citations as resources typed solveit-core:Citation for 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.ttl defines solveit-core:objectiveID and solveit-core:sortOrder, both on Objective, and both used by the knowledge base on all 24 objectives. techniqueID, weaknessID and mitigationID were already declared, so objectiveID was the one identifier property missing. sortOrder is an xsd:integer giving the position of an objective in investigation order.
  • solveit-core:hasReference is an owl:ObjectProperty with range solveit-core:Citation, in place of an owl:DatatypeProperty with range xsd: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 in core_classes_examples.ttl and every identifier already agreed with the knowledge base, so only the form changed.
  • scripts/validate_kb_conformance.py checks 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.yml and validate-and-build-docs.yml, and in generate-knowledge-base.yml before 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 with GITHUB_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.py in the solve-it repository mints terms through rdflib Namespace objects, which build an IRI by string concatenation and cannot fail, and it never reads the ontology. validate_ontology.py does not load the knowledge base, and validate_examples.py and validate_example_io.py load 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.yml now runs ontospy gendocs against a staging directory holding only the root-level solve_it_*.ttl files, in place of the repository root. scripts/build_docs_local.sh is 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, with a owl:Class , solveit-core:Technique, so ontospy rendered a class page for each one and listed it in the class index. Ten solveit-data:techniqueDFT-* entries were published as part of the ontology’s own vocabulary, all ten declared in solve_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 the rdf:type of 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 defines solveit-core:Technique, and the individual entries are instances of it. The examples themselves remain documented, by generate_examples_page.py.
  • The two shapes files are still read by the documentation build, so sh:NodeShape continues to appear in the class index.
  • generate_iri_redirects.py now 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-profile terms and nineteen are weakness-assessment terms: the parser tested for the three prefixes solveit-core:, solveit-analysis: and solveit-observable:, so the two modules added since it was written were skipped in full, and neither module had any resolvable IRI. The remaining two are solveit-observable:hasArtifact and solveit-observable:hasFile, which collided with the solveit-analysis: properties of the same local name. Both pairs are distinct properties with different domains, ForensicToolTagBasedReport against ArtifactSet and FileSet, 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 order Path.glob returned the files in, so it could change between runs with no edit to the ontology.
  • generate_iri_redirects.py fails, and writes nothing, if an entity’s namespace has no declared solveit- 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, so solveit-wa:hasEvaluation is 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.ttl declare hasCASEOutputClass solveit-observable:KeywordSearchResultSet for DFT-1049, DFT-1122, DFT-1123 and DFT-1125, in place of solveit-observable:KeywordSearchResult. The knowledge base had been updated to the set-valued class, so check_kb_drift in validate_examples.py reported 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 a KeywordSearchResultSet, so the declarations were the part that was behind.

[0.2.3] — 2026-08-20

  • validate-against-case-1.5.0.yml now 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 to main that touch a TTL file, by pull requests touching the same paths, and by generate-knowledge-base.yml calling it directly.
  • The call from generate-knowledge-base.yml is 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 using GITHUB_TOKEN, and GitHub does not start further workflow runs for pushes made with that token.
  • validate-against-case-1.5.0.yml now confirms that the SOLVE-IT shapes are in the graph it validates against before reporting a pass. The shapes reach case_validate because the two shapes files are matched by the solve_it_*.ttl pattern 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 breaks TechniqueIOTermShape is 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.yml is 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.yml checks out with fetch-depth: 2. The step that decides whether to bump the patch version tests whether VERSION changed by running git diff HEAD~1, and actions/checkout defaults to fetch-depth: 1, so HEAD~1 was 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 VERSION for 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

  • hasCASEInputClass and hasCASEOutputClass no longer declare rdfs: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 example case-investigation:exhibitNumber or uco-observable:filePath. 42 of the 173 terms the knowledge base references are properties. No single rdfs:range admits both classes and properties without also admitting everything else, so the restriction is now stated in SHACL rather than in OWL.
  • Added TechniqueIOTermShape to solve_it_core_shapes.ttl. Every term named as a technique input or output must be declared an owl:Class, owl:DatatypeProperty or owl:ObjectProperty. This replaces the rdfs:range removed above.
  • Added TechniqueIOTermConsistencyShape to solve_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, which TechniqueIOTermShape cannot 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 hasInput and hasOutput shortly, alongside the corresponding change in the knowledge base, so they are left unchanged here in order that the rename happens once.

  • scripts/validate_examples.py now requires knowledge base entities referenced in the examples to be written in the solveit-data: namespace. An example that writes :techniqueDFT-1002 against 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 in solve_it_examples/weakness_assessment_examples.ttl went unnoticed.
  • scripts/validate_examples.py now 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.py now follows rdfs:subClassOf when checking the input and output types of a performed action. A technique that declares Timeline as its input is satisfied by a SortedTimeline, 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

  • Technique now subclasses uco-action:Technique rather than case-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 by rdf:type, not by a property. The previous axiom sat on the metaclass and so made every catalogue entry a performed action.
  • SolveitInvestigativeAction retained, and is now the parent of every technique class. It remains the anchor for occurrence-level properties, so appliedMitigation is unchanged — its domain is satisfied by inference.
  • usedTechnique marked owl:deprecated. Retained so existing data parses.
  • hasCASEInputClass and hasCASEOutputClass changed from datatype properties with range xsd:anyURI to object properties with range owl: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-action 1.5.0 imports uco-core 1.5.0, which would put two versionIRIs of the same ontology in one import closure.
  • SHACL: retired SolveitInvestigativeActionShape, which required at least one usedTechnique; under the metaclass model there is no violating state left to detect. Added TechniqueShape, checking what OWL cannot express — that a technique is also declared owl:Class and carries an rdfs:subClassOf.
  • Example actions migrated from usedTechnique to rdf:type against the technique class, across six files.
  • validate_examples.py now 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)) to techniqueDFT-1121 (Index a data source for keyword searching). The action builds an index from a FileSet and an ArtifactSet and produces a KeywordIndex, which is what DFT-1121 declares; it was typed as a search.
  • Qualified the technique and weaknesses in weakness_assessment_examples.ttl with the solveit-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 rowid data property to SQLiteRecord.
  • Clarified comments on fieldType and hasBlobContent in 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 HypothesisedUserAccount to 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 HypothesisSet to support SOLVE-IT technique modelling.

[0.1.7] — 2026-06-25

  • Added VirtualizedDevice and VirtualizedComputer.

[0.1.6] — 2026-06-24

  • Added VideoFile and AudioFile.

[0.1.5] — 2026-06-24

  • Added HashSet (with HashSetEntry and HashVerificationResult) 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 PerformedTechnique to SolveitInvestigativeAction.
  • 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 hypothesisedDateTime property.
  • Added CASE input class support (hasCaseInputClass).
  • Added FileSet and FilteredFileSet; refined RedactedFileSet; added a PrioritizedDeviceSet example.
  • Acquisition/interface updates: added ReadWriteDeviceInterface, reworded read-only interface; accommodated screenshots and clock offsets as acquisitions; SHACL fix for ClockOffsetMeasurement.
  • Split forensic image containers into subclasses by contents (PhysicalImageContainer, LogicalImageContainer).
  • Added BitstreamRandomAccessed and LiveOSDeviceInterface.
  • Added BrowserCacheData.
  • Mitigation now subclasses InvestigativeAction.
  • 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 PerformedTechnique linking performed actions to techniques and applied mitigations; Technique changed to subclass InvestigativeAction rather than UcoObject.
  • 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 DataAcquisition and subclasses with acquisition error records.
  • Updated CASE/UCO alignment from 1.3 to 1.4.0.
  • Infrastructure: GitHub Pages documentation at ontology.solveit-df.org with IRI redirects; daily knowledge base RDF endpoint; MIT licence.