Serving the namespace

Version: 0.1.0-draft Status: normative for what the namespace serves. The deployment is an operational decision recorded here because it is nearly made already.

JigDAW's premise is that a significant component is identified by an IRI and that the IRI dereferences. The vocabulary is a significant component, so the same rule applies to it. A project that tells plugin authors to publish dereferenceable IRIs and does not dereference its own has an argument it has not taken seriously.

What is already true

purl.org/stuff is under our control, and measured on 2026-09-16 it behaves like this:

Request Lands on Result
purl.org/stuff/plugin-universe/ plugin-universe.com/ns/plugin-universe.ttl 200, text/turtle, 32673 bytes
purl.org/stuff/jigdaw/ hyperdata.it/xmlns/jigdaw/ 404
purl.org/stuff/valis/ hyperdata.it/xmlns/valis/ 404
purl.org/stuff/transmissions/ hyperdata.it/xmlns/transmissions/ 404
hyperdata.it/xmlns/ itself 200

So there is a wildcard rule mapping purl.org/stuff/<name> to hyperdata.it/xmlns/<name>, and plugin-universe has a specific override on top of it that points at its own site.

The configuration that serves this is deploy/nginx/vocab.conf, and the files it serves are generated into deploy/vocab/ by npm run build:vocab. Both are validated by deploy/nginx/check.sh, and a test fails if the deployed copy of the vocabulary drifts from vocabs/jigdaw.ttl.

JigDAW needs no PURL administration. http://purl.org/stuff/jigdaw/ already resolves to https://hyperdata.it/xmlns/jigdaw/. Putting the vocabulary there is the whole job. A specific override to a jigdaw.org, were there ever one, would be an optimisation and not a requirement.

What the namespace must serve

The namespace IRI, http://purl.org/stuff/jigdaw/, MUST serve the vocabulary, content-negotiated:

Accept Response
text/turtle vocabs/jigdaw.ttl
application/ld+json the same vocabulary as JSON-LD
text/html a page a person can read

text/html is the default when no preference is expressed, so pasting the namespace into a browser shows something useful rather than downloading a file.

Each term, such as http://purl.org/stuff/jigdaw/module, MUST resolve. This is a slash namespace, so each term is a distinct IRI and a server sees the request. It MUST answer 303 See Other to the vocabulary document, following Best Practice Recipes for Publishing RDF Vocabularies recipe 3.

303 rather than 200 because the term denotes a property or a class, not a document, and answering 200 would assert that the thing identified is the page returned. It is the one place where the distinction has a practical consequence, because a reasoner that conflates the two starts inferring that a property is a document.

Serving the vocabulary with Access-Control-Allow-Origin is REQUIRED, for the same reason it is required of a plugin profile: a browser fetching it cross-origin cannot read a response without it.

The gap this exposes

Individual terms dereference for nobody in this family today. purl.org/stuff/plugin-universe/supportedPlatform redirects to plugin-universe.com/supportedPlatform and returns 404, because the override is a prefix replacement that maps the namespace root correctly and everything below it to the site root.

trn: dereferences as of 2026-09-18. It is the vocabulary all four projects share and the one JigDAW's profile format is built on, and for as long as anyone had been publishing profiles that use it, purl.org/stuff/transmissions/ landed on a 404. It now answers 200 with 208 terms, content negotiated, with Access-Control-Allow-Origin and a 303 from every term, served the same way this one is from ~/github/transmission/deploy/.

So a JigDAW profile's trn:role, trn:accepts and trn:produces now resolve to definitions, which was the largest remaining dead link in anything this project publishes.

Where things are served

Two different questions, often confused, and the answer is different for each.

The vocabulary is served at https://hyperdata.it/xmlns/jigdaw/, which is where the existing PURL wildcard already points. It needs no PURL administration, and nothing about it should move to an application host: a vocabulary outlives the applications that use it.

Plugins and the DAW are served from strandz.it, on the same host as hyperdata.it and plugin-universe.com. Plugin IRIs mint under https://strandz.it/jigdaw/plugins/.

That is an application host rather than a PURL, which is a deliberate difference from the vocabulary and from plugin-universe's catalogue IRIs. A plugin IRI is a retrieval address as well as a name: it has to resolve to the code. Putting it behind a PURL would add a redirect to every fetch of every resource for no gain, because the profile already separates identity from retrieval (see the rebasing rule in docs/plugin-profiles.md): a plugin mirrored anywhere keeps its canonical IRI and is fetched from wherever it was found.

Never mint under the serving domain

An IRI in JigDAW's own vocabulary MUST be minted under http://purl.org/stuff/jigdaw/ and never under whatever host currently serves it.

The PURL is the identity and the host is an implementation detail. Minting under the serving domain means that moving the site breaks every IRI ever published, including those written into other people's project files, which cannot be corrected by us. This rule is plugin-universe's and it is the reason its plugin IRIs survive a change of domain.

Dereferencing it from a browser needs the https form

Measured 2026-09-17, following the redirects as a browser does:

Hop Status Access-Control-Allow-Origin
http://purl.org/stuff/jigdaw/ 302 absent
https://purl.org/stuff/jigdaw/ 307 *
https://purl.archive.org/stuff/jigdaw/ 302 *
https://hyperdata.it/xmlns/jigdaw/ 200 *

Only the opening hop is a problem, and it is enough to stop the fetch: a CORS request must pass the check on every response in a redirect chain, not only the last. From a page served over https: it fails earlier still, because http: is mixed content and never leaves the browser.

So a browser based consumer MUST dereference https://purl.org/stuff/jigdaw/. Everything from that hop onward carries the header and the vocabulary answers correctly.

This does not change what the IRIs are. They are minted on http: because that is the identifier, and it is what the sibling projects do. An identifier is not a fetch instruction, and http://purl.org/stuff/jigdaw/abi and https://purl.org/stuff/jigdaw/abi are different IRIs that must not be used interchangeably in data.

It is written down because the project tells plugin authors to dereference these IRIs, and an author who does it the obvious way from a web page gets a network error and reasonably concludes the vocabulary is broken. It is not: purl.org does not send the header on its plain http: redirect, and that hop is not ours to change.