-
Notifications
You must be signed in to change notification settings - Fork 151
Federation evaluation
An evaluation of LinkedDataHub's federation architecture
Status: evaluation of LinkedDataHub 5.6.0 (master, July 2026). Companion to Audit roadmap; same register — every empirical claim cites path:line or a commit, every normative claim cites an axiom or an external spec.
This document evaluates whether LinkedDataHub's interface design — read-write Linked Data CRUD via the SPARQL 1.1 Graph Store Protocol, per-dataspace SPARQL endpoints discovered through Link headers, and hypermedia affordances carried in-band — is a viable foundation for a distributed data platform of independently operated nodes (self-hosted and cloud), with uniform UX regardless of whether a local or remote dataspace is accessed. Three verdicts, defended below:
- Feasible? Yes. The federation mechanism is complete for reads and transport-complete for writes — including cross-node authentication via WebID delegation, which exists and is verified end-to-end in the code (§2.5). The remaining gaps (trust enrollment at scale, remote-edit UX, change propagation, cache coherence) are incremental, not architectural (§6).
- Crucial constraint? Yes, in a precise sense. Interface uniformity is necessary, not merely sufficient, for uniform UX in an open world of nodes — nodes not known when the client was written. §4 states this as a parametricity-style theorem with an explicit converse, and uses its contrapositive as an audit instrument: every observed local/remote UX divergence names the specific axiom it violates.
-
Right track? Yes. The strongest evidence is negative space: the pen-test findings (LNK-002/003/009) cluster exactly at the endpoints that violate interface uniformity (
/add,/transform,/generate), and the planned PATCH refactor (AUDIT-ROADMAP P1.5) closes the security holes and the uniformity violations with one change. Where the design is uniform, it is also safe and federable; where it is not, it is neither.
Can a client — a human through the UX, or a program through the API — interact with any dataspace through one interface, such that node location is unobservable except in latency?
Definitions used throughout:
- Node — one LinkedDataHub instance (one deployment of the Docker stack).
-
Dataspace — an end-user/admin application pair on a distinct origin (
config/dataspaces.trig); a node hosts one or more dataspaces. - Local / remote — relative to the origin the browser session is on. A remote dataspace may live on the same node (sibling subdomain) or on an independently operated node; the evaluation asks whether that difference is observable.
- Federation — N independently operated nodes whose dataspaces interlink; a user of one node reads and writes documents on another with the same UX.
- Uniform UX — same affordances, same rendering, same interaction loop regardless of target.
Method: the fact base (§2) was established by reading the server filters, the GSP and SPARQL resource classes, the XSLT client, the configuration, and the roadmap/wiki/audit documents. The formal apparatus (§4) is a semi-formal argument in the tradition of using free theorems as design contracts — its limits are stated in §4.5, not hidden.
Each subsection ends with the uniformity property it establishes; §4's axioms cite these properties rather than raw code.
Every document in the hierarchy corresponds to a named graph; the document URI is the graph name. CRUD is the Graph Store Protocol verb set, implemented in DocumentHierarchyGraphStoreImpl (src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DocumentHierarchyGraphStoreImpl.java): GET returns the graph, PUT creates/replaces it (establishing sioc:has_parent/sioc:has_container hierarchy), POST appends, DELETE drops it.
PATCH is the disciplined write primitive (:362): body is application/sparql-update; exactly one operation; only INSERT/WHERE and DELETE WHERE forms (:374); the GRAPH keyword is rejected with 422 (:377-383) — a PATCH is therefore always scoped to exactly the request graph. Blank nodes introduced by the update are skolemized; a graph left empty is deleted.
Property P1. The write interface is identical at every node, and every write addresses exactly one graph = one document.
-
{base}/sparql— the dataspace's SPARQL endpoint (server/model/impl/SPARQLEndpointImpl.java), routed to the backing service fromconfig/system.trig. It is read-only; state changes go through GSP PATCH only. -
{base}/ns— the ontology endpoint (resource/Namespace.java), a read-only SPARQL endpoint over the application ontology, seeded from the ad-hoc ontology repository (commit b53a2cfe5). SPARQL updates are rejected with 405 (Namespace.java:163,:175).
Property P2. Query capability is per-dataspace, discoverable in-band (§2.3), and never a write channel.
ResponseHeadersFilter (server/filter/response/ResponseHeadersFilter.java) emits, per response:
| Link rel | Target | Condition |
|---|---|---|
acl:agent |
authenticated agent URI | agent present (:68) |
acl:mode |
acl:Read/acl:Append/acl:Write/acl:Control
|
one per authorized mode, per request (:72) |
sd:endpoint |
{base}/sparql |
local responses only (:78) |
lapp:application |
application resource URI | local responses only (:85) |
ldt:ontology |
application ontology URI | local responses only (:88) |
ac:stylesheet |
XSLT stylesheet URI | local responses only (:91) |
ldt:base |
application base URI | error responses (server/mapper/ExceptionMapperBase.java:96) |
The local-only rels are suppressed on proxied responses (ResponseHeadersFilter.java:74-77) because ProxyRequestFilter forwards the remote origin's Link headers verbatim (ProxyRequestFilter.java:402-408) — including the remote sd:endpoint and, critically, the remote acl:mode, so a client can know its capabilities at the remote node without any out-of-band arrangement.
Property P3. Affordances arrive in-band; the client holds no per-node configuration.
acl:modemakes capability a datum of the response, not an assumption of the client.
The client extracts sd:endpoint/ldt:base from the response's Link headers and stamps them onto the target tab pane as data-endpoint/data-base DOM attributes (xsl/bootstrap/2.3.2/document.xsl:472-475). The accessor functions read the active pane's values, falling back to the local application (xsl/bootstrap/2.3.2/client/functions.xsl:64-81). Consequences:
- ContentMode blocks (charts, maps, queries) resolve
sd:endpoint()per pane, so they transparently query the remote dataspace's endpoint when a remote document is displayed. - Multiple open panes can face different nodes concurrently; there is no global "current node" state to go stale.
- The same XSLT 3 templates render local and proxied resources (SSR shell + Saxon-JS CSR); the rendering path does not branch on origin.
Property P4. Above the transport layer, client behavior is a function of the response, not of the serving node.
The cross-node authentication chain exists in the code and is complete in mechanism:
-
Outbound (
server/filter/request/ProxyRequestFilter.java:216-227): proxied requests go throughgetExternalClient(), which is constructed with the node's client keystore (Application.java:698) — outbound TLS therefore presents the node's secretary WebID certificate. For WebID sessions the filter registersWebIDDelegationFilter, which addsOn-Behalf-Of: <agent-uri>(client/filter/auth/WebIDDelegationFilter.java:48); for OAuth2 sessions,IDTokenDelegationFilter(JWT cookie +On-Behalf-Of). -
Inbound (
server/filter/request/auth/WebIDFilter.java:139-147): the receiving node authenticates the connecting secretary via WebID-TLS, dereferences the principal's WebID profile (throughURLValidator— the LNK-004 SSRF mitigation), and accepts the delegation iff the profile asserts<secretary> acl:delegates <principal>. Otherwise the delegation is rejected.
Two caveats carried into §4's corollaries: the acl:delegates trust wiring is manual and O(users × nodes) — the mechanism is in-band and axiom-conformant, but enrollment is not yet automated (C1); and ID-token delegation carries the code's own warning — "It's not secure to use ID token delegation to 3rd party servers!" (IDTokenDelegationFilter.java:30) — so the OAuth2 path does not federate across operators (C2).
Authorization, by contrast, is deliberately not propagated: the local ACL is skipped on the proxy path (the proxy is a transport function), and the remote node enforces its own ACL as sole authorizer. This is a design principle worth naming, not a gap: authentication federates; authorization stays sovereign.
Property P5. Agent identity is a dereferenceable URI meaningful at every node; delegation is itself expressed as Linked Data in the principal's profile, verifiable by any node through the uniform read interface.
There is no CORS filter anywhere in LinkedDataHub, Core, or Web-Client — a verified absence, and deliberate. Client-side, ldh:href() (xsl/bootstrap/2.3.2/imports/default.xsl:205-221) wraps every cross-origin URI in ?uri= on the page origin, per the in-code comment: "so the request stays same-origin (carries credentials, then ProxyRequestFilter forwards)." The proxy forwards the HTTP method and entity verbatim (ProxyRequestFilter.java:238-241), so PUT/POST/PATCH/DELETE against remote documents are transport-complete today. The HTML bypass (ProxyRequestFilter.java:148-162) exempts browser shell requests; server-side rendering of external RDF was removed after it proved a resource-exhaustion vector (see CLAUDE.md, "Linked Data Proxy and Client-Side Rendering").
This is one of two possible topologies, with a real trade:
| Proxy-mediated (LDH) | CORS-direct | |
|---|---|---|
| Credentials | same-origin, just work | remote must allow credentialed CORS; client certs cross-origin are painful-to-impossible in browsers |
| Trust config | none in the browser | per-node CORS policy |
| Addressing | uniform ?uri= on page origin |
raw remote URIs |
| Cost | every remote byte transits the local node; latency; availability coupling; the historical DDoS surface | remote fetch is the remote's problem |
Property P6. The same request shape reaches any node; the local node acts as transport, never as authority, for remote resources.
The design is Fielding's uniform-interface constraint (REST, §5.1.5) instantiated with RDF as the representation algebra and GSP as the manipulation protocol:
| Fielding's interface constraint | LDH instantiation |
|---|---|
| Identification of resources | document URI = named graph name (P1) |
| Manipulation through representations | GSP verbs on RDF representations; PATCH as scoped SPARQL Update (P1) |
| Self-descriptive messages | standard RDF serializations + RFC 8288 Link headers (P3) |
| Hypermedia as the engine of application state |
acl:mode, sd:endpoint, ldt:ontology as in-band affordances driving the client (P3, P4) |
The distinctive move is that uniformity holds at the data-model level, not just the protocol level: because every representation is RDF, one generic client renders anything any node serves. The plain Web achieves this for human-readable content (HTML); LDH extends it to machine-writable content — which is exactly the part the plain Web never federated (§5).
This is a parametricity-style argument, not a mechanized proof. Where the analogy is strict and where it is heuristic is stated in §4.5.
Definitions. A node N is a pair (D_N, I_N): a set of RDF documents and an interface implementation. A client C is interface-typed if its behavior is a function only of (status, media type, body, Link relations) of responses, and it emits only requests permitted by the axioms below, addressed through a fixed translation href (identity locally; ?uri=-wrapping cross-origin).
A1 (Uniform addressing). Every document is denoted by an absolute URI, and the URI is the only name a client needs:
doc : URI → Graph. (Instantiated by P1.)
A2 (Uniform manipulation). The complete write interface of every node is the GSP verb set — GET, POST, PUT, DELETE, and PATCH restricted to a single
GRAPH-free SPARQL Update targeting the request graph — with identical request/response semantics at every node. No write is expressible outside this set. (Instantiated by P1, P2. The final clause is violated today by/add,/transform,/generate— corollary C6.)
A3 (Self-description). Every response is an RDF graph in a negotiated standard serialization plus in-band control data (Link headers per RFC 8288); interpreting it requires knowledge of vocabularies, never of the serving node. (Instantiated by P3.)
A4 (In-band affordances). The capabilities the requesting agent may exercise next at the target — base, query endpoint, permitted modes, presentation — are advertised inside the response, never presumed from client configuration. Formally: the client's next-action set is a function of the response alone. (Instantiated by P3, P4.)
A5 (Portable identity). Agent identity is a dereferenceable URI (WebID) meaningful at every node; delegation of identity is itself expressed as Linked Data in the agent's profile (
acl:delegates), verifiable by any node through the interface of A1–A3. (Instantiated by P5.)
Lemma L (Proxy transparency). For any URI u, the representation obtained at the local address
?uri=u equals the representation obtainable at u by the same agent, up to (i) the Link-rel suppression/forwarding rules of §2.3 and (ii) staleness bounded by the cache TTL, with authentication reified as delegation per A5.
L is a lemma, not an axiom, deliberately: it is the implementation obligation the proxy must discharge, and every topology-related gap below is a measurable deviation from L.
Let client C be interface-typed against Σ = {A1…A5}, let all nodes satisfy Σ, and let the proxy satisfy L. Then for any resource state served identically by nodes N₁ and N₂ with the same agent-capability assignment, C's observable behavior — rendering, affordances offered, and the sequence of subsequent requests modulo
href— is identical regardless of which node serves it. Equivalently: C cannot define a test that distinguishes local from remote documents, except by latency.Converse (open-world necessity). If C must exhibit uniform behavior against nodes not known when C was written, then C can rely on nothing but the interface; hence Σ is not merely sufficient for uniform UX but necessary.
Forward direction — by induction on C's interaction trace. Every step C can take is: (i) dereference a URI (A1), (ii) apply a GSP verb (A2), (iii) interpret a response using vocabulary knowledge only (A3), (iv) select next actions from advertised affordances (A4), or (v) present identity and have it verified node-independently (A5, L). None of these steps observes node identity except through the URI's authority component, and the one place the client touches authority — ldh:href() — is a single chokepoint below the abstraction line, applied uniformly. A deterministic client fed bisimilar inputs produces bisimilar outputs; any behavioral divergence between N₁ and N₂ must therefore originate in a difference of served graphs or advertised capabilities, contradicting the premise. ∎ The concrete witness is §2.4: the same XSLT templates render both cases, and endpoint/base are read from the response-stamped pane, not from configuration.
Converse — by contradiction. Suppose C behaves uniformly over an open world yet relies on some node-specific fact φ not guaranteed by Σ. The open world contains a node lacking φ (that is what "open" means); C's behavior there diverges. So the only facts a uniformly-behaving open-world client may rely on are the node-invariant ones — precisely the interface guarantees. ∎ Note the necessary scoping: a closed-world client can special-case every known node and achieve uniform UX with zero uniformity — at O(N) client complexity. The theorem's force is the quantifier: uniformity is what makes client complexity O(1) in the number of nodes. This is Fielding's uniform-interface rationale, restated with the quantifier made explicit.
The analogy: like a polymorphic function f : ∀α. F(α) → G(α), an interface-typed client cannot branch on the node because the node is not observable through the interface type — uniform UX "for free" in Wadler's sense. The href translation plays the role of the natural transformation that parametricity quotients out.
The contrapositive of the theorem is an audit instrument: each observed local/remote divergence witnesses a specific violation by a specific party.
| # | Gap (with evidence) | Violated clause | Character |
|---|---|---|---|
| C1 |
acl:delegates trust wiring is manual, O(users × nodes) (§2.5) |
A5 holds for wired pairs, not all pairs — quantifier weakening, not violation in kind; the mechanism is in-band, the enrollment is out-of-band | unimplemented automation |
| C2 | ID-token delegation audience-bound and self-documented as insecure to third parties (IDTokenDelegationFilter.java:30) |
A5 violated for OAuth2 agents across operators — their UX bifurcates local vs remote | needs a decision |
| C3 | Non-LDH remotes emit no Link rels; client falls back to local sd:endpoint/ldt:base (client/functions.xsl:64-81) |
A4 degradation is masked rather than surfaced — fallback can misattribute capability (querying the local endpoint about remote data) | design refinement |
| C4 | Varnish caches ?uri= responses with TTL-only invalidation (no xkey from the remote) |
Lemma L violated in the time dimension: staleness bound differs local vs remote, making location observable through freshness | unimplemented; fixed by eventing (C5) |
| C5 | No LDN/WebSub push; GitHub-backed versioning plan has no cross-instance coherence | not an axiom violation — Σ covers the synchronous request/response plane only; federation also has an event dimension on which Σ is silent | honest scope extension |
| C6 |
/add, /transform, /generate perform server-side fetches (pen-test LNK-002/003/009; URLValidator loopback residual) |
A2 violated: writes expressible outside the GSP verb set. The empirical punchline: the security findings and the uniformity violations are the same set of endpoints | already planned (P1.5 PATCH refactor) |
| C7 | No federated SPARQL — no SERVICE orchestration; sd:endpoint() is one node per pane |
not a violation — per-node query uniformity (P2) holds — but caps cross-node joins at client-side composition | unimplemented |
| C8 | Proxy topology: every remote byte transits the local node; DDoS history; availability coupling (§2.6) | not a violation of any axiom; a cost of how L is discharged. Roadmap tension: client-side loading relieves C8 but reopens the credential problem the no-CORS/proxy design solves | fundamental trade, must be decided |
The distribution is the finding: of eight gaps, exactly one (C6) violates a core axiom, and it is the one already scheduled for removal — with the pen-test as independent confirmation that the violation was also the vulnerability.
- Strict: the forward direction is an ordinary observational-equivalence argument over identical inputs; the contrapositive audit method (§4.4) is genuinely load-bearing and repeatable.
-
Heuristic: (i) HTTP is untyped — nothing enforces interface-typing; the discipline is maintained by code review, so the honest frame is Reynolds-style representation independence used as an architectural invariant, not a language-guaranteed free theorem. The single-
ldh:href()-chokepoint invariant is checkable and worth protecting with tests. (ii) Timing, staleness, and failure are side channels outside the interface type — real users observe latency, and strict parametricity would forbid observing it; the theorem's "up to latency" is a scope cut, not a proof step. (iii) The necessity claim holds only under open-world quantification (§4.3); stated plainly so that the strongest form of the claim is also the defensible one.
| Dimension | Plain Web | Solid | ActivityPub | LinkedDataHub |
|---|---|---|---|---|
| Read uniformity (A1, A3) | HTML GET — the original uniform read | LDP GET; uniform in spec, fragmented across pod servers | AS2 JSON-LD GET; dereference often optional in practice | GSP GET + follow-your-nose; spec-conformant |
| Write uniformity (A2) | none — every form is bespoke; no machine-readable write contract | LDP PUT/POST + N3 Patch; uniform in spec, uneven in deployment | non-uniform: C2S barely deployed; S2S is inbox-POST of activities, no CRUD on remote objects | GSP verbs incl. disciplined PATCH — strongest of the four |
| Affordance discovery (A4) | gold standard for humans (links, forms); opaque to machines |
WAC-Allow header, type indexes — partial |
none in-band; behavior hardcoded per implementation | richest machine-readable set: acl:mode, sd:endpoint, ldt:ontology, ac:stylesheet
|
| Identity portability (A5) | per-site accounts; none | WebID + Solid-OIDC — most standardized story | actor URIs portable in principle, server-bound in practice | WebID-TLS + in-band acl:delegates; works, enrollment manual (C1) |
| Query | none | none required by spec | none | per-dataspace SPARQL + ns/, discoverable in-band |
| Topology / propagation | pull only; no write federation | CORS-direct browser→pod, pull; Solid Notifications emerging | push (inbox delivery) — the one dimension where AP leads | proxy-mediated, pull-only (C5, C8) |
The plain Web is the control group. A1+A3+A4-for-humans made the read web federate globally — the largest federated information system ever built. The absence of uniform machine writes (A2) is precisely why write federation never emerged there: every write is a bespoke form against a bespoke backend. This is the strongest empirical support for the "crucial constraint" claim: the one axiom the Web lacked is the one capability the Web never federated.
Solid is the nearest cousin. It shares A1/A3/A5 ambitions and has a stronger standardization story for identity. The live differences: granularity (LDP resource vs named graph — LDH's document=graph identity gives PATCH a natural, enforceable scope, §2.1); query (Solid has no query axiom at all — LDH's discoverable read-only endpoints are a real differentiator); and topology (CORS-direct vs proxy-mediated — mirror-image trade-offs, §2.6). On delegation, Solid is ahead on paper (OIDC flows), LDH on having delegation verified against profile data in shipping code (§2.5).
ActivityPub has inverse strengths. It solved push federation (the dimension LDH lacks, C5) by abandoning uniform read-write: a client cannot CRUD an arbitrary remote object; every capability must be encoded as bespoke activity vocabulary, and uniform UX is approximated by copying data to where the user is — the antithesis of location transparency, with its well-known consistency artifacts (partial threads, ghost replies). ActivityPub is the demonstration of what federation without A2 costs.
LinkedDataHub is the only system of the four attempting all five axioms plus query. That is the claim to evaluate on its own merits — and the reason its gaps (§4.4) are worth closing rather than routing around.
Gap classification. Of the eight corollaries: one is a fundamental trade to decide (C8, topology); one needs a policy decision (C2, cross-operator OAuth2); the rest are unimplemented-but-design-conformant (C1, C3–C7). No gap found contradicts the architecture. The corrected fact base — delegation exists (§2.5), remote-write transport exists (§2.6), remote acl:mode is forwarded (§2.3) — moves the verdict from "promising but identity-blocked" to mechanism-complete; enrollment- and UX-blocked.
What must be true, in order:
-
Scalable identity enrollment (unsolved design — C1, C2). Automate the
acl:delegateswiring. Note the elegant recursion available here: enrollment is itself a PATCH on the principal's profile document via the uniform interface — the architecture can bootstrap its own trust topology. Separately: deprecate cross-operator ID-token forwarding per the code's own warning, or adopt a token-exchange profile. -
Remote-edit UX (implementation gap). Surface the forwarded remote
acl:modeinto edit affordances. Transport is done (§2.6); this is the roadmap's "editing documents in a remote LDH app" item, and it is smaller than the roadmap implies. -
Uniformity convergence (implementation gap, converging — C6). Land the P1.5 PATCH refactor removing
/add//transform//generateserver-side fetches: closes LNK-002/003/009 and restores A2's "no write outside the set" clause in one move. - Change propagation (unsolved design — C4, C5). LDN inbox and/or WebSub between nodes. One mechanism fixes both cache coherence for proxied content and cross-instance versioning notification.
- Dataspace self-description (implementation gap). VoID/DCAT descriptions so dataset boundaries are A4-discoverable at dataspace granularity — required for "search across my nodes", not for follow-your-nose browsing.
- Topology decision (fundamental trade — C8). A hybrid is available: client-side loading for public reads (relieves the proxy), proxy for authenticated traffic (keeps the credential story that the no-CORS design depends on). The DDoS history (CLAUDE.md) is the evidence base for deciding where the line goes.
- Multi-node deployment guidance (documentation). Lowest risk, currently absent.
Items 1 and 4 are the genuine research/design debt. Neither is caused by the uniform interface — they are what remains after it.
"Is SPARQL an out-of-band, non-uniform escape hatch?" In general, yes — an endpoint taking arbitrary queries is not resource-oriented. LDH bounds it three ways: the endpoint is discovered in-band (sd:endpoint Link rel — an affordance, not configuration); it is read-only (writes stay in A2, §2.2); and it is per-dataspace, so its scope is a discoverable dataset, not the world. Honest concession: query results are not hypermedia-complete — a result set carries no affordances. SPARQL is best described as a second, parallel uniform interface for reads, and this document says so rather than pretending it composes into REST.
"Do Link headers count as hypermedia, or out-of-band metadata?" They are in the message envelope, standardized (RFC 8288), and content-type-independent — HATEOAS requires in-message controls, not in-body ones, and for RDF media types there is no <a href> to use. Concession: an RDFa-only processor that never sees headers loses them. The v6 XHTML+RDFa direction (wiki: XHTML+RDFa as LDH v6 Document Format) is the opportunity to mirror affordances in-body, strengthening A3/A4. Note also the caching interaction: acl:mode varies by agent, so responses carrying it must Vary accordingly.
"Doesn't ?uri= mint a second identity for the same resource?" The proxy URI is a transport address, not an identifier — the client treats the inner URI as identity throughout (ldh:parse-href unwraps it, imports/default.xsl:227-245). But the duality is observable in bookmarks and cache keys, and the purist resolution (client-side direct loading) is currently blocked by the credential problem the proxy solves (§2.6). The tension is real and stated, not rhetorically dissolved.
"The PATCH restrictions (single op, no GRAPH) are non-standard." They are a profile, not a fork: a strict subset of SPARQL 1.1 Update semantics, rejected loudly (422) rather than reinterpreted. The restriction is what enforces A2's one-graph scoping — the discipline is the feature.
"The theorem's 'same document set' premise is unrealistic — nodes disagree, caches go stale." Correct; the theorem idealizes consistency, and C4/C5 measure the deviation. Items 4–5 of §6 are exactly the machinery needed to approximate the premise in practice.
"Is uniform UX even desirable — shouldn't users know which node they're on?" Uniformity of operation is not concealment of origin. Provenance display (origin, acl:agent) is orthogonal and should remain visible; the theorem constrains what the client must do differently (nothing), not what it may show (anything).
Q1 — Feasible for a distributed platform of self-hosted and cloud nodes? Yes. The uniform interface is implemented (§2, P1–P6), the federation path is transport-complete including authenticated cross-node access (§2.5–2.6), and the ordered list in §6 contains no item that invalidates the interface — the hard remainders (identity enrollment, eventing, versioning coherence) are additions alongside Σ, not corrections to it.
Q2 — Is the uniform interface a crucial constraint for federated webapps? Yes, with the precise sense supplied by §4: against an open world of nodes, interface uniformity is necessary — without Σ, uniform UX requires node-specific client code or configuration, and client complexity grows O(N) in nodes; with Σ, node location is unobservable modulo latency and rights, at O(1) client complexity. The comparison (§5) supplies the empirical leg: the axiom the plain Web lacked (A2) is the capability it never federated, and the system that dropped A2 deliberately (ActivityPub) pays for it in bespoke vocabulary and consistency artifacts.
Q3 — Is LinkedDataHub on the right track? Yes. Every mechanism the theorem requires exists in shipping code; the violations of Σ are few, localized, and already on the roadmap (P1.5 closes the only core-axiom violation); and the roadmap's direction of travel (PATCH refactor, proxy redesign, v6 RDFa) strengthens the axioms rather than weakening them. Priorities, in order: identity enrollment (§6.1), change propagation (§6.4), dataspace catalog (§6.5) — with the note that §6.2 (remote-edit UX) is the cheapest visible win, since only affordance wiring is missing.
| Rel | Local response | Proxied response | Error response |
|---|---|---|---|
acl:agent |
emitted | emitted | — |
acl:mode |
emitted (local ACL) | forwarded from remote | — |
sd:endpoint |
emitted (local) | suppressed; remote's forwarded | — |
lapp:application |
emitted | suppressed | — |
ldt:ontology |
emitted | suppressed; remote's forwarded | — |
ac:stylesheet |
emitted | suppressed; remote's forwarded | — |
ldt:base |
— | — | emitted |
Sources: ResponseHeadersFilter.java:68-91, ProxyRequestFilter.java:402-408, ExceptionMapperBase.java:96.
| Claim | Evidence |
|---|---|
| PATCH discipline (single op, no GRAPH, 422) | DocumentHierarchyGraphStoreImpl.java:362,374,377-383 |
ns/ read-only ontology endpoint |
Namespace.java:163,175; commit b53a2cfe5 |
| Link-rel emission and proxy suppression | ResponseHeadersFilter.java:68-91,74-77 |
| Remote Link forwarding | ProxyRequestFilter.java:402-408 |
| Delegation outbound (secretary cert + On-Behalf-Of) |
ProxyRequestFilter.java:216-227; Application.java:698; WebIDDelegationFilter.java:48
|
Delegation inbound (acl:delegates verification) |
WebIDFilter.java:139-147 |
| ID-token delegation warning | IDTokenDelegationFilter.java:30 |
| Method + entity forwarding (remote writes) | ProxyRequestFilter.java:238-241 |
| HTML bypass (anti-resource-exhaustion) | ProxyRequestFilter.java:148-162 |
Same-origin ?uri= wrapping |
imports/default.xsl:205-221 |
| Per-pane endpoint/base state |
document.xsl:472-475; client/functions.xsl:64-81
|
| Dataspace public/internal config split |
config/dataspaces.trig; config/system.trig
|
| SSRF residuals at non-uniform endpoints | pen-test LNK-002/003/009; AUDIT-ROADMAP P0.2, P1.5 |
- Fielding, R. Architectural Styles and the Design of Network-based Software Architectures (2000), §5.1.5.
- RFC 8288, Web Linking.
- SPARQL 1.1 Graph Store HTTP Protocol; SPARQL 1.1 Update.
- Reynolds, J. C. Types, Abstraction and Parametric Polymorphism (1983); Wadler, P. Theorems for Free! (1989).
- Solid Protocol; Web Access Control (WAC); ActivityPub (W3C REC); Linked Data Notifications (LDN); WebSub; VoID; DCAT.
- LinkedDataHub wiki: Roadmap, XHTML+RDFa as LDH v6 Document Format, Graph Versioning Implementation Plan.
- Audit roadmap (this repository).