Chapter 17. Building Up

This chapter runs the synthesis direction constructively — the synthesis theorem as a build log. Start with the derived atoms and compose a working application space, defining each layer by what Part II forced and each concrete technology by the factor it inhabits.

The dataspace

What the synthesis yields needs a name, and the name should do for state what “website” did for documents. Call it a dataspace: one party’s stake in the data web — the unit of publication, ownership, and federation. A website serves documents under an origin; a dataspace serves state under an origin. Documents are included, since they are projections of that state. Machines are invited, since the state itself dereferences. (The database literature has used the word for pay-as-you-go integration — Franklin, Halevy, and Maier, 2005; the sense here is the web-native one.) The definition needs one primitive Part II never used, and the web ships it — Chapter 1’s pattern, holding one last time:

O        the set of origins                               (RFC 6454)
I∣o      the URIs under origin o

An origin is not a new kind of name. RFC 6454 computes it from the URI — scheme, host, port — so O is a quotient of I. The namespace falls into regions, one per party, and “one party’s stake” acquires a type. The definition has four components and no more — an origin, and three names in its region, because on the web every published thing is a name:

Dataspace = (o, ont, e, x)      o ∈ O;   ont, e, x ∈ I∣o   (17.1)
name component in words
o the origin read-write linked data at every document under it
ont the ontology what the domain is, stated as one namespace
e the SPARQL endpoint the same state, projected by query
x the stylesheet declarative rendering, extended by override

Internal storage — file, memory, triplestore — has no row. It is invisible to consumers, as S1 demands.

Behind the four names stands one state S, in the shape of Prop. 9.2: quads, grouped by their fourth position into a family of named graphs. S(u) is the graph named u, and every graph name is a document URI under o. The gloss column is then four laws, each an earlier result arriving at deployment grain.

Documents

Dereference is graph lookup — select(u, S) = S(u), the fourth position as the address (Prop. 9.2). There read is defined (S4) and write accepts a delta (Prop. 7.1). And the obligation that makes the data linked: every name under o in a fact position of S has read(name, S) defined — mint a name only if you serve its description. AWWW §3.5 asked for this as a SHOULD; (17.1) holds it as a condition of being a dataspace at all. So the state is not only composable but recursively discoverable: each reference in a fact is an address, and dereferencing it returns more state, whose references point onward in turn. Documents may also nest. Parent and child are ordinary facts, so a document’s children are one more selection. Addressing stays flat — one graph per document — and the hierarchy is a convention over it, not a new kind of resource.

One state

The endpoint e answers ⟦q⟧ posed to S itself — the same S the documents project. “Projecting the same state” is an equation, and a second store that drifts from S breaks it observably.

Domain as data

S(ont) is schema in the shape of (5.3): the domain’s classes and properties, stated as facts — state like any other, composed by the same law. The build log below shows what reads it.

Total rendering

x dereferences to the arrange term, generic in B.8’s sense. The build log below looks at it more closely.

One entity makes the four concrete. GET …/panel-14 returns the graph of facts about that panel. PATCH …/panel-14 sends a delta — (D⁻, D⁺). And the endpoint answers any query that ranges over it. One state, three doors, each an HTTP request you can make by hand.

That write door holds four methods, and each is Prop. 7.1’s delta at a fixed value — PATCH the general case, POST, PUT, and DELETE its corners:

method fixes result
POST D⁻ = ∅ S′ = S(u) ∪ D⁺ append (a merge)
PUT D⁻ = S(u) S′ = D⁺ replace, creating if absent
DELETE D⁻ = S(u), D⁺ = ∅ S′ = ∅ remove
PATCH any D⁻, D⁺ S′ = (S(u) ∖ D⁻) ∪ D⁺ general

The Graph Store Protocol leaves PATCH informative; realized, it is a graph-scoped SPARQL Update. HTML forms speak only POST, so a form’s delta arrives through the RDF/POST bridge (Chapter 9). Zoom out from one graph to the whole dataset and the same four return on quads: GET a dataset, POST appends quads, PUT replaces it, DELETE removes it — the extended form some triplestores implement.

Interactive exhibit (online edition): the write methods on …/panel-14. Pick GET, POST, PUT, DELETE, or PATCH — the delta (D⁻, D⁺) snaps to that method’s row, and the graph updates by S′(u) = (S(u) ∖ D⁻) ∪ D⁺. The same panel graph the chapter reads, now writable by hand.

Note what (17.1) omits: S is not a component. The store the gloss just called invisible appears nowhere in the tuple, so invisibility holds by construction rather than by discipline — S1, lifted from factor to system. Two deployments with the same four projections are the same dataspace.

And the union law returns. Federation adds one proof obligation, and the types discharge it (B.9). Distinct origins are disjoint regions of I, so two dataspaces’ graph names never collide, and the union of their states is again well-formed. Every document is still under exactly one origin, and attribution survives the merge because the fourth position carries it. Federation is the union law: merge, and be done.

The price of alignment

Merge, and be done. And here the objection that Chapter 5’s scope note deferred arrives at full strength: union is cheap; alignment is not. Two dataspaces describe the same turbine. Each minted its own name, because minting is free. The union holds two disconnected descriptions and joins nothing. Two ontologies cover one domain and share no term. The merge laws guaranteed mechanics, never convergence. So, says the objection, the integration cost the model claimed to dissolve has merely moved. Granted: the cost moved, and where it moved decides everything. The cost is universal, because no model makes strangers agree on names. So the question is never whether alignment costs, but what you hold before aligning, and what aligning yields.

Before aligning: the unaligned union is well-formed state — both descriptions present, queryable, published, rendered by the vocabulary-blind base term the build log below introduces (B.8). The worst case here is not yet joined; every other column of the audit offers cannot merge (two JSON documents do not compose at all; two schemas, no better).

After aligning: an alignment is one more fact — an equivalence, a subclass, a subproperty, in the shape of (5.3). The fourth position attributes it to its asserter (Prop. 9.2), it can be retracted as a delta (Prop. 7.1), and it composes by union like everything else. A mapping published this way is stated once and serves the whole web. The integration industry holds the same knowledge as a join buried in pipeline code, per pair of systems — unattributable, unshareable, priced N × M forever.

Even the failure mode improves. The literature rightly distrusts the identity link — the careless equivalence that propagates error through every join it touches. Here that link is a visible error, with an asserter and an inverse. The pipeline’s version of the same mistake has neither, nor even a name, because nothing outside the pipeline can see it.

And convergence has a deployed existence proof at full web scale. Vocabularies converge the way the document web converged: by adoption, not negotiation — publish, dereference, reuse, the same unilateral move as linking to a page whose owner was never asked. Schema.org spread across tens of millions of sites in exactly this shape, because consumers with reach — the search engines — made the alignment worth making. Alignment follows demand; that is this book’s argument in miniature. It is also the honest reading of the nineties (Chapter 8). The substrate was built for machine consumption and standardized twenty years before machines consumed it, so every cost of convergence went unmet — not refuted, only unfunded.

The build log

The build log takes the least familiar factor first. The ontology is the component the derivation predicts and the industry outsources to code: the domain, stated as facts. A dataspace’s ontology imports the vocabularies it builds on — union applied to schema — and everything downstream reads it as data. Forms are constructed from it (Chapter 7’s construction half: read the patterns, render inputs); selections range over it; layouts match on it. Ontology-driven is data-driven one level up, and it is what makes the generic engine generic: the domain travels in the state, so nothing domain-shaped remains to be hardcoded.

The build log, factor by factor:

factor occupied by the derived result, deployed
state a triplestore behind the Graph Store Protocol — the SPARQL suite’s HTTP companion, whose direct graph identification makes the request URI the graph name — one named graph per document the fourth position (Prop. 9.2) as an address — attribution and location coincide
domain a namespace ontology per dataspace, importing the vocabularies it builds on imports resolve by union — vocabulary is data and composes like it
select a SPARQL endpoint per dataspace S4: query results and graphs are resources with URIs of their own
arrange XSLT over the canonical serialization — a base stylesheet naming no vocabulary, per-vocabulary overrides layered by the language’s import mechanism Chapter 6’s seam occupied; S3’s substitution, performed in daily practice
present CSS in continuous service since 1996
write HTML forms encoding graphs (Chapter 9’s RDF/POST bridge, deployed in Chapter 18), written through the Graph Store Protocol’s unsafe methods Chapter 1’s unsafe methods at graph grain — POST appends, PUT replaces, DELETE removes; the delta itself a PATCH, a graph-scoped SPARQL Update carrying its two sets

flowchart LR
    S(["S · dataset"]) --> e[["SPARQL (e)"]] --> D(["Data"]) --> x[["XSLT (x)"]] --> T(["Tree"]) --> css[["CSS"]] --> Doc(["Doc · webpage"])
    Doc --> form[["HTML form"]] --> delta(["(D⁻, D⁺)"])
    delta --> upd[["PATCH<br/>a graph-scoped SPARQL Update"]]
    upd -- "S′(u) = (S(u) ∖ D⁻) ∪ D⁺" --> S

The build log as a picture — (4.1) at deployment grain, closed as in Chapter 7. Along the read spine the endpoint e runs select (SPARQL), the stylesheet x runs arrange (XSLT, ⟦t⟧ ∘ canon), CSS runs present(17.1)’s components bound to deployed standards. The return arrow is the write side: a form (Chapter 9’s bridge) yields a delta (D⁻, D⁺) (Prop. 7.1), carried as a PATCH — a graph-scoped SPARQL Update. Under S4 every rounded node is a web resource with a URI of its own.

The arrange row carries the most machinery, and it deserves a closer look. The names the layered term treats specially are exactly the names the dataspace’s ontology declares — B.8’s relative genericity, deployed. Unmatched state falls back to the base rendering rather than to nothing: every graph renders; declared vocabulary renders better. The stylesheets share their templates across the wire: one library, imported by a server-side stylesheet that emits documents and a browser-side one that binds events. Saxon runs the first, and SaxonJS with IXSL runs the second — two processors, one set of terms. Chapter 7’s mobility of evaluation, running. The convergence shares rendering code too, by running the same framework on both sides (Chapter 14’s hydration); here the sides share templates without sharing an engine, because the language’s semantics is closed. And independent evolution shows up as operations rather than theory: data, selection, layout, and style invalidate independently, per factor, cache entry by cache entry — the four timelines, running as infrastructure.