Serve raw ontology graphs without RDFS inference - #337
Open
namedgraph wants to merge 4 commits into
Open
Conversation
namedgraph
force-pushed
the
raw-ontology-serving
branch
from
August 2, 2026 12:36
7327548 to
b8e472d
Compare
Resolve the application ontology's owl:imports closure natively via ontapi (OntModelFactory.createModel over a ScopedGraphRepository view) instead of manually flattening the closure and materializing an RDFS-inferred model. No inference is applied anymore — every consumer (constructor/constraint inheritance, client-side (rdfs:subClassOf)* queries) traverses hierarchies explicitly. rdfs:Class terms are promoted to owl:Class in a separate union member so no document graph is polluted; closure union graphs are cached in a bounded map on Application, keyed by ontology URI. The shared repository now only ever holds raw per-document graphs, which ProxyRequestFilter serves directly for closure documents — asserted triples only, identical to a direct document GET. The DESCRIBE fallback over the in-memory closure (terms minted in external namespaces) is inference-free as well. This fixes inferred rdf:type rdfs:Resource leaking into proxied namespace documents, where the extra type produced multi-token @typeof and silently degraded View blocks to a generic property list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ontapi consults GraphRepository.contains() before get() when resolving an ontology's imports closure. PrefixGraphRepository.contains() reports cache state (loaded graphs), not resolvability, so every import that resolves through a bundled location mapping (dh, sp, spin, foaf, sioc, sd), SPARQL-first loading or HTTP was answered with false on first resolution — and ontapi silently substituted an empty ontology graph for it (its ignoreUnresolvedImports fallback). The closure kept its shape but lost the content of every such import: SPIN constraints vanished, so validation enforced nothing (422 tests wrote through, eventually applying invalid dataspace settings and cascading into NPEs), and vocabulary term lookups came up empty. This is what failed the HTTP test suite in CI. contains() now attempts resolution through the backing repository (which loads and caches the graph) after the cache checks, reporting absent only for genuinely unresolvable ids. Adds a production-shaped regression test: ns# ontology importing the SPARQL-seeded ldh# vocabulary with its transitive imports resolved through the real bundled location mappings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ontapi keys imports under their declared ontology IRIs, which need not be repository entries: a content-addressed upload is cached under its uploads/ URI while declaring a foreign ontology IRI. The doc-URI aliasing loop called repository.get() on such declared IRIs, which fell through to an HTTP dereference of the foreign IRI (e.g. https://example.org/test) during ontology load — failing the load and the ontology-import-upload-no-deadlock HTTP test. Guard the loop with isCached() so only graphs the shared repository actually holds get aliased. Adds a mismatched-IRI import case to the closure regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The admin ontologies/namespace/ document stores the ontology but the closure keys it under the <ns#> ontology URI, so a proxied GET of the document URI is answered by the closure DESCRIBE fallback — the document's own #-fragment term descriptions — not the raw graph branch. Assert on a class minted in the document's hash namespace (mirroring the original #related_View regression) instead of the made-up-namespace classes, which only appear under their own namespace document URI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
namedgraph
force-pushed
the
raw-ontology-serving
branch
from
August 2, 2026 18:40
5553543 to
205d102
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
View blocks rendered as generic property lists instead of executing their
spin:query. Root cause:OntologyFiltermaterialized an RDFS-inferred imports closure, andProxyRequestFilter's namespace short-circuit served proxied?uri=requests via DESCRIBE over that inferred model.ldh:View a rdfs:Class+ rulesrdfs7b/rdfs9type every instancerdf:type rdfs:Resource, so proxied ontology documents carried an extra type on every term — producing multi-token@typeofthat the client's exact-equality*[@typeof = '&ldh;View']match no longer satisfied.Changes
No RDFS inference over application ontologies. An audit showed the reasoner was vestigial: constructors recurse over direct superclasses, SPIN constraint collection walks
rdfs:subClassOfitself, and every client ontology query already uses(rdfs:subClassOf)*property paths. Theowl:importsclosure is now resolved natively by ontapi (OntModelFactory.createModelover a newScopedGraphRepositoryview) as a live union graph — the manual flatten/infer/materialize pipeline is deleted.rdfs:Classterms are promoted toowl:Classin a separate union member (ontapi's OWL2 named-class factory doesn't recognize barerdfs:Class), so no document graph is polluted. Closure union graphs are cached in a bounded map onApplication; per-requestOntModelwrapping is preserved.Two ontapi interaction subtleties surfaced by the HTTP test suite, both pinned by the new
OntologyClosureCIReproTest:GraphRepository.contains()beforeget()when resolving imports;ScopedGraphRepository.contains()now answers resolvability (attempting the load) instead of cache state, otherwise every bundled-mapped/SPARQL/HTTP import was silently replaced by an empty graph — stripping SPIN constraints from the closureRaw document graphs on the wire, uniformly. The shared repository now only holds raw per-document graphs.
ProxyRequestFilterserves closure documents with their raw graphs — asserted triples only, identical to a direct document GET — guarded byisCachedso arbitrary external URIs can't trigger repository loading outside the SSRF-validated external-client path. The DESCRIBE fallback remains for terms minted in external namespaces and is now inference-free.Namespace's no-query GET reuses the shared raw cache instead of a per-requestcreateRepositorySPARQL round-trip. Invalidation updated inClearOntologyandValidatingModelProvider.Also fixed in passing:
UninstallPackageno longer reads a materialized closure when a package URI is a loaded app ontology, and admin ontologies importing each other can no longer fold one closure's artifacts into another on the shared system repository.With the server no longer serving inferred types, LDH-authored blocks carry single-token
@typeofagain — the client XSL is untouched relative to develop.Test plan
OntologyImportsCharacterizationTestrewritten to pin: eager closure resolution, zero inference in the union, raw document graphs untouched (isomorphism), promotion not leaking into raw graphs,getOntClassrecognition ofrdfs:Class-only terms, import-cycle tolerance.OntologyClosureCIReproTestpins the production-shaped closure (real bundled location mappings) and the mismatched-IRI upload importhttp-tests/proxy/GET-proxied-ontology-ns.shextended: proxied ontology-document hash terms served with nordf:type rdfs:Resource; same negative assertion on the DESCRIBE fallbacktypeofin the DOM🤖 Generated with Claude Code