Develop#315
Draft
namedgraph wants to merge 14 commits into
Draft
Conversation
…gation Proxy server-side fetches set On-Behalf-Of (WebIDDelegationFilter), and the backend response carries the asserted agent's WebID in the Link header. The URL-keyed varnish-frontend entry then replays that response to subsequent anonymous requests for the same URL+Accept. Test fires the proxy request as owner, then asserts that an anonymous direct request returns 403 and that no acl#agent appears in the Link header. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Proxy server-side fetches set On-Behalf-Of (WebIDDelegationFilter), and the backend response echoes the asserted agent's WebID in the Link header (acl#agent). The previous vcl_recv only passed for Client-Cert + HTML, so the delegated RDF response was stored under a key that ignored the asserted identity — any subsequent anonymous request to the same URL+Accept replayed the cached 200 and read back the previous agent's identity and ACL grant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stamp body.cursor=progress when ldh:http-request is issued for the document RDF and backlinks fetches, and reset to default when the corresponding response handlers run, so the user gets feedback that the 3D graph is loading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Newly-appended tab-body elements were defaulting to class="tab-pane active", which briefly left two panes carrying the 'active' token (the new one and the currently-active local one) between append and ldh:ActivateTab. Code running in that window — notably ldh:LeftSidebar, which reads ldt:base() and sd:endpoint() off the active pane — would see ambiguous state and crash. Pass class="tab-pane" explicitly so only ldh:ActivateTab promotes a pane to active. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing Step A/B covered the proxy-delegation hop (On-Behalf-Of asserted in the HTTP header). It misses the symmetric path where the LDH server-side client presents its keystore cert at TLS to nginx: the backend stamps acl#agent into the Link header for the authenticated 200, and the URL-keyed cache slot ignores the asserter, so a later anonymous request reads the response back. Steps C/D drive that path directly — authenticated owner GET with Accept: application/rdf+xml, then anonymous direct GET, asserts 403 and no acl#agent in the Link header. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…atic/ The previous Client-Cert block only passed for HTML and a few specific endpoints. RDF/Turtle/JSON-LD/SPARQL-results responses fell through to hash and got stored even though the backend stamps acl#agent into the Link header for every authenticated response, leaking that identity (and the asserter's ACL grant) to any anonymous reader of the same URL. The replacement rule is the actual semantic boundary: /static/* is served by Tomcat's default servlet (web.xml:365-371), bypasses Jersey, carries no identity in headers, and is safe to share across cache callers. Every other path is potentially user-specific when the request authenticates, so it must pass. The previously-listed If-Match / /access / /acl/agents/ sub-clauses are subsumed by Client-Cert + !/static/ → pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the response-body dumps and `[Client-Cert path]` tag prefixes — single echo + exit 1, matching the convention of sibling tests like GET-proxied-internal-403.sh. Step name still printed so a CI failure points at the right assertion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The typed branches in getResponse() parse the upstream entity into a Model/ResultSet and re-stamp ETag/Last-Modified off the parsed value. For HEAD responses the body is empty by HTTP semantics, so that parse yields an empty Model/ResultSet whose hash-derived ETag disagrees with the GET ETag for the same URL. Previously masked by varnish-frontend: a GET-populated cache entry served HEAD requests with the original ETag, so the proxy's HEAD upstream fetch read body bytes from cache and the re-stamped validator happened to match direct. After widening the Client-Cert bypass in vcl_recv, both fetches go fresh to backend and the proxy's empty-body parse is exercised for real, producing a wrong ETag. For HEAD, skip the typed branches entirely and forward the upstream's ETag/Last-Modified verbatim via overlayHeaders(copyValidators=true). The proxy's response now agrees with the direct response. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bind the target URI via setIri() instead of string-concatenating it into the query text, eliminating the SPARQL injection surface on a URI containing metacharacters. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ID auth DocumentHierarchyGraphStoreImplTest covers the stateless logic (getChangedResources, getLastModified, writeFile/writeFiles guards and file I/O) via a CALLS_REAL_METHODS mock, since the class only exposes a heavyweight @Inject constructor. StreamRDFOutputWriterTest covers the RDF-import streaming path: null guard, getter round-trip, and the non-RDF media type -> BadRequestException branch. The CSV transformation itself is covered upstream in CSV2RDF. ProxiedWebIDFilterTest covers Client-Cert header PEM parsing into an X509Certificate, absent header, and malformed input. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Migrate vocabularies to Jena ontapi; add ontology characterization tests - Bump client dependency to 4.3.1-SNAPSHOT (pulls jena-ontapi transitively via Core) - Migrate 19 vocabularies off the deprecated-for-removal org.apache.jena.ontology API to org.apache.jena.ontapi (OntModelFactory/OntSpecification), with a top-of-class static JenaSystem.init() guard (ontapi NPEs if a vocab class is the first Jena touch) - Add characterization tests pinning current ontology behavior so the migration can be proven to retain it: imports closure + RDFS materialization, dual-key cache (addDocumentModel), SPARQL-first resolution (OntologyModelGetter), vocab triples Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Phase D: dissolve DataManager + migrate ontology pipeline to ontapi Completes the dissolution in LinkedDataHub (0 [removal] warnings, was ~90): - DataManagerImpl -> SameSiteSourceResolver (RDFSourceResolver subclass, same-site restriction) - OntologyModelGetter -> OntologyRepository (SPARQL-first PrefixGraphRepository subclass) - DataManagerFactory -> SourceResolverFactory (provides request-scoped RDFSourceResolver) - Application: per-app OntModelSpec/OntDocumentManager -> per-app OntologyRepository; global repository + resolver; remove PrefixMapper/LocationMapper/OntDocumentManager wiring - OntologyFilter/ClearOntology: ontapi OntModelFactory.createModel with OWL2_DL_MEM_RDFS_INF + materialize into OWL2_DL_MEM cached in the repository; dual-key import-closure caching preserved - request ontology property Optional<Ontology> -> Optional<OntModel> (ontapi) across OntologyFactory + ~8 consumers (.getOntModel() dropped) - Validator, ProxyRequestFilter, ValidatingModelProvider, Install/UninstallPackage: DataManager/OntModelSpec cache ops -> repository - characterization tests adapted to new API (OntologyRepositoryTest, OntologyFilterTest); 69 tests green Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix OntologyFilter: flatten owl:imports closure manually, not via ontapi union-graph repository OntModelFactory.createModel(graph, spec, repository) registers graphs in an OntUnionGraphRepository keyed by ontology ID, which collided with the same graph already in our flat PrefixGraphRepository cache (OntJenaException: 'Another graph with name <...#> is already in the hierarchy', thrown at runtime on the first /ns request). Replace it with explicit owl:imports closure traversal (loadClosure) that unions the base + imports into one graph, runs RDFS inference over that, and materializes — so createModel is only ever called WITHOUT a repository (no union-hierarchy registration). Encapsulates the duplicated OntologyFilter/ClearOntology load logic into OntologyFilter.loadOntology. OntologyImportsCharacterizationTest now exercises loadOntology and asserts the materialized closure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix empty constructed response: use OWL1_FULL_MEM so rdfs:Class is recognized GET /ns?forClass=...#Item returned an empty graph: dh:Item is declared 'a rdfs:Class' (dh.ttl), and the ontapi OWL2_DL_MEM profile I'd used does not recognize rdfs:Class as an OntClass, so Namespace's getOntClass(uri) returned null and no SPIN constructor ran. Legacy OntModelSpec.OWL_MEM is OWL 1 Full (recognizes rdfs:Class); the correct ontapi mapping is OWL1_FULL_MEM, not OWL2_DL_MEM. Applied across OntologyFilter pipeline + all vocab holders. OntologyImportsCharacterizationTest now guards getOntClass(rdfs:Class) != null. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Use twirl 1.2.0-SNAPSHOT; drop redundant SPIN personality registration twirl 1.2.0 re-bases the constraint model onto its own SPIN personality, so the ontapi ontology model can be passed straight to SPINConstraints.check; LDH no longer needs to register SPIN into the global personality. - twirl 1.1.0 -> 1.2.0-SNAPSHOT - Remove SP.init(BuiltinPersonalities.model) from Application (Web-Client Constructor reads sp:text directly; nothing else needed the global registration) - Add SPINConstraintValidationTest: guards the Validator path and the raw-ontapi-via-twirl-rebase path Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: re-run against deployed twirl/core snapshots * ci: re-run against deployed twirl/core snapshots * Normalize ontologies to owl:Class; use OWL2_FULL_MEM profile The document/LDT/ACL ontology classes were declared bare rdfs:Class, which no OWL2 ontapi profile recognizes as an OntClass — forcing OWL1_FULL_MEM (which in turn bans named individuals, breaking SD). Declare them owl:Class (dual with rdfs:Class) and switch all OntSpecification usages from OWL1_FULL_MEM to OWL2_FULL_MEM, so getOntClass/forClass works and named individuals are allowed. - dh.ttl/ldt.ttl/lacl.ttl: class declarations now 'a rdfs:Class, owl:Class' - vocab holders + OntologyFilter + ConstructForClass: OWL1_FULL_MEM -> OWL2_FULL_MEM - remove dead 'import com.atomgraph.client.locator.PrefixMapper' (deleted in Web-Client) - OntologyImportsCharacterizationTest: assert owl:Class (not rdfs:Class) is recognized Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add debug output to add-property-constraint and GET-proxied-ontology-ns tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Removed debug output * Tests for RDFS ontology imports * Promote rdfs:Class to owl:Class during ontology materialization OWL2 profiles do not recognise bare rdfs:Class as OntClass, so third-party vocab terms declared only as rdfs:Class (e.g. sp:Describe in sp.ttl) were invisible to getOntClass() lookups, returning empty forClass constructor responses. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Repoint PrefixGraphRepository import to Web-Client; replace deprecated Model.write with RDFWriter - Update imports to com.atomgraph.client.util.jena.PrefixGraphRepository (moved out of Core): Application, OntologyFilter, OntologyRepository, SourceResolverFactory, SameSiteSourceResolver + tests - XSLTWriterBase: use RDFWriter instead of deprecated Model.write, keeping plain RDF/XML Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * SNAPSHOT bump --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
No description provided.