NIKOLAI
Versioning policy
How NIKOLAI elements change over time, and what an implementer citing a NIKOLAI URI can rely on.
Identifiers are immutable
Every element has a URI of the form /nikolai/element/<slug>, and every track has /nikolai/track/<slug>. These resolve to the same conceptual entity for the lifetime of the vocabulary. If an element needs to change conceptually rather than editorially, it becomes a new element with a new slug; the old one is deprecated with a successor pointer, never silently retargeted or removed.
Deprecation, not removal
No element has been deprecated yet — nikolai-v0.1 is the first release. When deprecation is needed, NIKOLAI follows the same policy as the CASRAI Dictionary: the element continues to resolve at its original URI, carries a deprecation notice, and points to its successor.
The release tag: nikolai-v0.1
NIKOLAI is versioned independently of the CASRAI Dictionary's vYEAR.N scheme — it is its own DefinedTermSet (casrai.org/nikolai#set) with its own version line. The current release is nikolai-v0.1, published 18 September 2026. This is a deliberately conservative tag: NIKOLAI has not yet reached a 1.0 commitment to API or schema stability, and the tag says so honestly rather than implying more maturity than the vocabulary has earned.
A version bump is a deliberate, human decision — it is not automatic, and it is not the same event as a content re-seed (below). Bump the published version string in exactly one place, src/lib/nikolai/constants.js's NIKOLAI_VERSION, when:
- Minor (v0.1 → v0.2, or v0.x → v1.0 once schema-stable): elements or crosswalk rows are added, or an existing element's definition is materially expanded without changing its scope. Existing citations remain valid.
- Major (v1.x → v2.0, once past 1.0): an element's scope changes materially, a controlled-vocabulary value is renamed or removed, or the crosswalk match-type semantics change. Reviewed before shipping, not applied silently.
How content actually gets updated: the content-hash seed
Unlike the CASRAI Dictionary's per-term editorial workflow, NIKOLAI's Wave-1 content ships as a single structured data file, seeded in one pass. The mechanism, in wp-content/mu-plugins/casrai-nikolai.php:
1. Edit the element/crosswalk data (see "How to add or update an element" below). 2. On the next WordPress request, casrai_import_nikolai_elements() computes md5(serialize($rows)) over the current data file. 3. If that hash differs from the stored casrai_nikolai_elements_seed_hash option, the importer runs: every element is upserted by slug (existing posts are updated in place, not duplicated), and the hash is written back. 4. If the hash is unchanged, the importer is a fast no-op on every request -- this is NOT a per-deploy migration step, it runs on every WordPress 'init' and only does real work when the data actually changed.
This means updating an element's definition or adding a crosswalk row is a data-file edit plus a redeploy of the WordPress image — no manual "run the seeder" step, and no risk of forgetting to re-seed after a content fix. It also means a data-only typo fix does not need a version-string bump; only a deliberate release does.
Concurrency note, learned the hard way at nikolai-v0.1's own launch: the import runs inside an add_option()-based mutex — the first WordPress worker to hit a changed hash acquires a real, DB-atomic lock, and every other concurrent worker's import attempt bails immediately rather than racing it. The first deploy shipped without this lock and briefly double-created 20 elements before the fix landed; see the changelog.
How to add or update an element
- Edit the element's record in the seed data (see
casrai-nikolai-seed.php's own header comment for the exact file and shape). - Every crosswalk row you add or edit MUST carry
is_shadow: trueanddeclared_by: nullunless the named organisation has actually filed a Mapping Declaration — the import will silently skip any row that omits the flag, and the write endpoint rejects it outright with a 400. - Every element's
operational_definitionshould cite at least one real, external primary-source document insource_of_record— not only NIKOLAI's own prior research notes. - Rebuild and redeploy the WordPress image (
wp-content/Dockerfile); the content-hash guard handles the rest on the next request. - Add a release entry to the changelog describing what changed, and decide whether it warrants a version bump per the rules above.
Relationship to the CASRAI Dictionary's versioning
NIKOLAI and the CASRAI Dictionary are versioned independently — a CASRAI Dictionary release does not imply a NIKOLAI release, and vice versa. See the CASRAI Dictionary's own versioning policy for that product's twice-yearly cadence, which NIKOLAI does not follow.







