Code Lists

The vocabulary for code lists — governed, externally maintained sets of coded entries (language tags, licence identifiers, currency codes, media types, time zones) that are projected into Kanonak packages from their source of truth by a producer, never hand-typed. One CodeList record per generated package states where its entries came from and which revision of the source they reflect; every entry carries the same few facts, so one renderer, one deprecation rule and one lookup serve the whole family.

A code list is reference data that someone else governs: the IANA language subtag registry, the SPDX licence list, ISO 4217 currencies, the IANA media-type and time-zone registries. Each is an authoritative, slowly changing list of coded entries with labels and a lifecycle (entries get added, deprecated, and replaced). Kanonak packages need to reference those entries as resources, not carry them as strings, so each list becomes a package under codes.kanonak.org — and because the list is governed elsewhere, the package is generated, never authored.

One way in. Every code list is produced by a producer: a small plugin, implementing the SDK's package-producer contract, that reads the source in the format the source is expressed in (record-jar, CSV, JSON, XML) and projects it into a package through the SDK's PackageBuilder. Format readers are shared; the mapping from one source's records to one list's entries is the plugin. The producers and the generated packages live in the kanonak-protocol/code-lists repository, published as their own publisher at codes.kanonak.org — kanonak.org keeps the protocol and its vocabularies, including this one; a projection of someone else's data lives with its own publisher. The producers run on demand — never on a schedule, so a source that revises often does not become a stream of package versions nobody asked for. A run fetches the source, compares its digest with the last projection, projects on change, validates, and opens a pull request adding the new version. A person decides when to run it and merges; the site deploy publishes. Nothing is ever overwritten or deleted.

The version is the source's own. A generated package's version is derived from the source's version marker — the registry's file date (2026-09-17 becomes 2026.9.17), a list version (3.27 becomes 3.27.0) — never from when the producer ran. The same source bytes always produce byte-identical output, and the pipeline proves it by projecting twice.

Provenance is in-band. Each generated package holds one Code List resource naming each Source it was read from (a prov.Standard with its URL, the Source Version the source declared, and the Source Digest of the exact bytes read), the Producer that projected it, and the Entry Class and Entry Count. A list may have several sources (a current and a historic list); the first is the one the package version derives from. A reader can verify the package against its sources without trusting the pipeline.

Every entry looks the same. An Entry carries its Code (the string the source uses — the BCP 47 tag, the SPDX identifier, the currency code), an rdfs.label, optional Alternative Label alternatives, and when it is retired, Deprecated plus Superseded By pointing at its replacement. Domain-specific facts are layered on by each list's own vocabulary (for language tags, the language-tag package). The uniform floor is what lets one renderer, one deprecation warning and one lookup work across the whole family.

Alternative LabelAn alternative name for the entry beyond its rdfs.label — a source often lists several ("Spanish" and "Castilian"). The first source description becomes the…CodeThe entry's code exactly as the source writes it — the BCP 47 tag, the SPDX licence identifier, the ISO 4217 currency code. The resource name is derived from…Code ListThe provenance record of one projected code list — exactly one per generated package. It names the source the entries were read from, the source's own version…CodeListShapeEntryOne coded entry of a code list. Every entry carries a code and a label; a retired entry carries owl.deprecated and, when the source names a replacement,…Entry ClassThe class (or classes) the list's entries are instances of.Entry CountHow many entries the package holds. A quick integrity check against the source, and a signal of the list's size before fetching it.EntryShapeProducerThe name of the producer plugin that projected this list, as registered in the producers workspace of the code-lists repository.SourceA source of truth the code list was projected from — an embedded prov.Standard carrying the registry's URL, the version it declared and the digest of its…Source DigestThe digest of the exact source bytes the entries were projected from, in the same `sha256:` form the lock file uses, so the projection can be verified and…Source VersionThe source's own version marker, verbatim — a registry file date, a list version number. The package version is derived from the first source's.