ADR 0002 — Align store frontmatter with the Open Knowledge Format
Status: accepted (2026-06-22)
Context
Google published the Open Knowledge Format (OKF) v0.1 on 2026-06-12 — a
vendor-neutral format for organizational knowledge. Its model is close to
demarkus's own: directory bundles of markdown, a cross-link relationship graph,
index.md hubs, and path-minus-.md as concept identity. Spec:
https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md
The one structural difference is where metadata lives. OKF carries it in the
document body as YAML frontmatter (required type; recommended title,
description, resource, tags as a YAML list, and timestamp). demarkus
carries metadata out of band: the on-disk version file is prefixed with a
store-managed frontmatter block that is stripped before the body is served, and
the catalog reads only the publisher keys. Syntactically both use a ---
block, but the data model differs.
Before this change, every publisher key was namespaced under a meta. prefix
on disk (meta.tags, meta.type). That prefix was not cosmetic — it was the
integrity boundary that prevented a publisher from supplying archived: true
or version: 999 and forging store state, because extractMetadata read only
meta.* keys.
We are pre-1.0, so the on-disk storage format is still free to change.
Decision
Adopt a split namespace in the store frontmatter so the persisted field names match OKF for the fields it defines, without losing the integrity boundary.
- Recognized OKF fields (
type,title,description,resource,tags,timestamp) are written bare.tagsis serialized as a YAML flow list (tags: [a, b]) to match the spec exactly. - Non-spec publisher keys (e.g.
importance, custom fields) keep themeta.prefix — demarkus's own metadata lane, and the anti-forgery boundary for the open-ended key set. - Reserved store fields (
version,previous-hash,archived) stay bare and unchanged. The boundary the prefix used to enforce is now enforced by name: areservedMetaKeysdenylist thatvalidateMetarejects andextractMetadatanever surfaces as publisher metadata.
Implementation is contained to protocol/store/store.go —
buildVersionFile (write), extractMetadata (read), validateMeta (reject
reserved). The in-memory metadata map stays bare-keyed, so the catalog,
handler, and filter layers are untouched; tags round-trips list↔csv, so the
map contract ("a,b") is unchanged. The spec change is recorded in SPEC.md
§9.4 / §8.1.
Consequences
- Back-compatible reads.
extractMetadatastill parses pre-changemeta.tags/meta.typewrites, so existing immutable versions and live servers (e.g.soul.demarkus.io) keep working. New writes use the bare form. - Vocabulary alignment, not interop. A single demarkus document's content
model is now OKF-compatible, but the store frontmatter is stripped before
serving and the
versions/layout is not an OKF bundle tree. demarkus does not yet serve or ingest OKF bundles. We deliberately do not claim "OKF compatible" as a normative conformance guarantee. - Sets up a 1:1 codec. Because the persisted field names are now the literal OKF names, a future import/export codec is a direct mapping rather than a translation table.
- Relationship framing. At the system level demarkus remains a superset: it layers versioning, a hash chain, QUIC transport, capability auth, and LOOKUP discovery on top of an OKF-compatible document.
Deferred
- An import/export codec (OKF bundle ↔ demarkus world) with frontmatter
reattachment on the served document and
index.md/log.mdconventions. - A conformance check against the OKF reference sample bundles.
- Scope decision parked: import-only vs round-trip vs server-native
content-negotiated bundle serving; and where it lives (
tools/demarkus-okfCLI vsclient/okfpackage).