Virtuoso 7.2 (OpenLink OSE)
Dependency specification
- Office XML metadata graph —
ioi-ext:OfficeXMLFacetwithioi-ext:dctermsCreated; linked toobservable:FileFacetprovidingfileNameand normalizedfilePath - $MFT graph —
ioi-ext:MftFacetwithcreated0x10($SI) andcreated0x30($FN); linked toobservable:FileFacetproviding normalizedfilePath
Matching is on case-insensitive comparison of normalized absolute observable:filePath values across two named graphs.
A document’s embedded Office XML creation minute must match the filesystem $SI creation minute for the same file path.
Contradiction condition
The embedded Office XML creation minute differs from the MFT $SI creation minute, indicating the document metadata and filesystem timestamp disagree. This catches either direction of timestamp manipulation while ignoring sub-minute skew, such as 14:26:00Z versus 14:26:37Z.
SPARQL signature
PREFIX core: <https://ontology.unifiedcyberontology.org/uco/core/>
PREFIX observable: <https://ontology.unifiedcyberontology.org/uco/observable/>
PREFIX ioi-ext: <https://ioi-framework.github.io/ns/ioi-ext/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?officeEntry ?fileName ?filePath ?xmlCreated
(MIN(?mftSiCreated) AS ?mftSiCreated)
(MIN(?mftFnCreated) AS ?mftFnCreated)
WHERE {
GRAPH <https://ioi-framework.github.io/cases/AF-012/graphs/office> {
?officeEntry a observable:File ;
core:hasFacet ?xmlFacet, ?officeFileFacet .
?xmlFacet a ioi-ext:OfficeXMLFacet ;
ioi-ext:dctermsCreated ?xmlCreated .
?officeFileFacet a observable:FileFacet ;
observable:fileName ?fileName ;
observable:filePath ?filePath .
}
GRAPH <https://ioi-framework.github.io/cases/AF-012/graphs/mft> {
?mftEntry a observable:File ;
core:hasFacet ?mftFacet, ?mftFileFacet .
?mftFacet a ioi-ext:MftFacet ;
ioi-ext:created0x10 ?mftSiCreated ;
ioi-ext:created0x30 ?mftFnCreated .
?mftFileFacet a observable:FileFacet ;
observable:filePath ?mftFilePath .
FILTER(LCASE(STR(?mftFilePath)) = LCASE(STR(?filePath)))
}
BIND(SUBSTR(REPLACE(STR(?xmlCreated), "T", " "), 1, 16) AS ?xmlCreatedMinute)
BIND(SUBSTR(REPLACE(STR(?mftSiCreated), "T", " "), 1, 16) AS ?mftSiCreatedMinute)
FILTER(?xmlCreatedMinute != ?mftSiCreatedMinute)
}
GROUP BY ?officeEntry ?fileName ?filePath ?xmlCreated
ORDER BY ?filePath
Graph IRI substitution
The checked-in rule uses the canonical placeholders:
https://ioi-framework.github.io/cases/AF-012/graphs/officehttps://ioi-framework.github.io/cases/AF-012/graphs/mft
The executor rewrites AF-012 to the active case ID at runtime.
Implementation note
The Office XML graph is very small compared with the MFT graph. The normalized filePath join eliminates the earlier filename-only Cartesian-product problem, and the GROUP BY + MIN() pattern keeps the result stable when residual duplicate MFT matches exist. Timestamp comparison is intentionally minute-precision to avoid false positives from normal sub-minute write skew while still detecting bidirectional mismatches.