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, projects it, refuses a version that would drop an entry, validates, and opens a pull request adding the new version. A person decides when to run it and merges; the site deploy publishes. A published version is never overwritten or deleted.
The version is the source's day and the producer's revision. A generated package's version is 1.{day}.{revision}: the day its first source was published (2026-09-17 gives 1.20260917.0) and the producer's revision, never when the producer ran. The source's own version marker is its Source Version. A list only ever adds entries, since a retired one stays, deprecated, so a link to an entry never stops resolving and the major stays 1. A fix to a producer that changes what it makes from a source already published raises its revision, so the correction is a new version. The same source bytes always produce byte-identical output, and the pipeline proves it by projecting twice.
Entries are named by their code in lowercase, as the protocol names an instance, with anything a name cannot carry folded to - (zh-hant, image-svg-xml). Every code these lists hold is case-insensitive by its own standard, and Code keeps it exactly as the source writes it.
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.