This document proposes an architecture for hosting, citing, versioning, and amplifying the discoverability of Requests for Comment (RFCs) produced by Common Fund Data Ecosystem (CFDE) working groups. The goals, in priority order:
- Knowledge sharing — make the content of RFCs easy to find, read, and reuse.
- Finding new users — reach people in neighboring domains who would not otherwise encounter the work.
- Citability and permanence — every RFC is a citable, archived, versioned object.
- Low maintenance burden — the process must be sustainable at a volume of roughly 5–10 RFCs per year, with minimal per-RFC scaffolding.
Comment collection is a secondary goal; the primary aim is dissemination.
A single monorepo for the working/discussion layer, with one independently versioned Zenodo record per RFC for the citable/archival layer, plus a rendered GitHub Pages "RFC Book" as the human-facing front door — and, for the subset of RFCs that define a standard, data resource, or policy, a linked FAIRsharing / re3data registration.
The key design principle is the separation of layers:
| Layer | System | Purpose |
|---|---|---|
| Working / discussion | GitHub monorepo + Issues/Discussions | Drafting, review, comment, version control |
| Presentation | GitHub Pages (rendered "RFC Book") | Readable, browsable, indexed front door |
| Citable / archival | Zenodo, one record per RFC | DOIs, archival guarantee, scholarly graph |
| Amplification | FAIRsharing / re3data (selective) | Cross-domain discovery of registrable artifacts |
The reason for splitting these is that the artifact you want to share (knowledge) and the activity you want to enable (comment) have different ideal homes, and the unit you want to cite (one RFC) differs from the unit GitHub naturally releases (a whole repo). Forcing one platform to do everything is where most such efforts bog down.
For FAIR purposes the deciding factor is the granularity of the citable, versioned object. Zenodo's native GitHub integration mints a DOI per release of a repository. So the real question is: should each RFC version independently, or should the series be the versioned object?
We want each RFC to version independently (so RFC-007 can reach v1.0 while RFC-003 is being superseded), but we do not want the operational overhead of a new repository per RFC.
Option A — One repo per RFC.
Each RFC gets its own release cadence, its own concept-DOI, and a cleanly scoped
discussion thread.
Cost: proliferation (5–10 new repos/year, each needing identical scaffolding —
CITATION.cff, .zenodo.json, license, CI), plus a discovery problem: nothing
ties the repos together except a naming convention, and cross-RFC linking becomes
manual.
Option B — One monorepo, many RFCs (the IETF / Rust / Kubernetes-KEP model). A single home, a natural index page, trivial cross-referencing, one set of scaffolding, one Discussions space. Naive cost: a Zenodo release of the monorepo would snapshot all RFCs together, so you could not cleanly cite or version one RFC independently — the DOI would point to "the collection as of release N."
Option C — One repo per working group. A middle ground: RFCs grouped by WG, each WG with its own Zenodo sub-community. Scales better than per-RFC repos, keeps related RFCs together, still allows per-RFC DOIs. A reasonable fallback if the single monorepo grows unwieldy.
Adopt the monorepo (Option B) for the working and presentation layers, but do NOT use the repo-granular GitHub→Zenodo release hook for archival. Instead, deposit each finalized RFC to Zenodo as its own record, driven by a per-RFC git tag and a CI job. This gives:
- monorepo convenience (one home, shared scaffolding, cross-linking, one index);
- per-RFC DOIs and independent version chains (the FAIR requirement);
- a Zenodo Community that gathers all RFC records under one umbrella.
The only discipline this requires: "publish RFC-N" is an explicit, tagged action
— not an automatic side effect of any repository release. A tag like
rfc-0007-v1.0 triggers a CI job that deposits only that RFC's directory to its
own Zenodo record (creating a new version if the concept already exists).
cfde-rfcs/
├── README.md # series overview + index + how-to-cite
├── CONTRIBUTING.md # the RFC process itself (lifecycle, statuses)
├── VERSIONING.md # version + DOI policy (see Part 3)
├── LICENSE # e.g. CC-BY-4.0 for text
├── 0000-template/
│ ├── rfc.md # the RFC body, with YAML front-matter
│ ├── CITATION.cff # per-RFC citation metadata
│ └── .zenodo.json # per-RFC Zenodo deposition metadata
├── 0001-some-topic/
│ ├── rfc.md
│ ├── CITATION.cff
│ └── .zenodo.json
├── 0002-another-topic/
│ └── ...
├── book.toml # mdBook config (renders the "RFC Book")
├── generate-index.py # builds the index page from front-matter
└── .github/workflows/
├── deploy-book.yml # build + publish GitHub Pages on merge to main
└── publish-rfc.yml # on rfc-NNNN-vX.Y tag → deposit to Zenodo
This mirrors the Rust approach, where every feature began as a Markdown file in a
GitHub PR and the repository serves as both the proposal system and the permanent
record of design decisions; a generate-book.py + book.toml toolchain renders a
browsable RFC Book deployed via a GitHub Actions workflow. We add the per-RFC
Zenodo deposition step that Rust does not need (Rust does not assign DOIs to RFCs).
The maximalist FAIR play is not to stuff each surface independently but to make them consistent and cross-linked. There are three surfaces:
Human- and machine-readable. GitHub renders a "Cite this repository" button from it and uses it to pass metadata toward Zenodo.
cff-version: 1.2.0
title: "CFDE RFC-0007: <Title>"
message: "If you use or build on this RFC, please cite it as below."
type: dataset # closest CFF type; see notes in VERSIONING.md
authors:
- given-names: Jane
family-names: Doe
orcid: "https://orcid.org/0000-0000-0000-0000"
affiliation: "University of Example"
# ROR via affiliation-meta where tooling supports it
abstract: >
One-paragraph summary of the RFC's contribution, written for a reader
outside the immediate working group.
version: "1.0.0"
date-released: "2026-01-15"
doi: "10.5281/zenodo.XXXXXXX" # the CONCEPT DOI (all versions)
license: CC-BY-4.0
keywords:
- common fund data ecosystem
- data standards
- <domain terms>
repository-code: "https://github.com/<org>/cfde-rfcs/tree/main/0007-some-topic"
url: "https://<org>.github.io/cfde-rfcs/0007-some-topic.html"
references:
- type: report
title: "CFDE RFC-0003: <prior related RFC>"
doi: "10.5281/zenodo.YYYYYYY"This is where the rich, FAIR-critical fields live that CFF does not carry.
{
"title": "CFDE RFC-0007: <Title>",
"upload_type": "publication",
"publication_type": "technicalnote",
"description": "<HTML or text abstract>",
"version": "1.0.0",
"publication_date": "2026-01-15",
"language": "eng",
"license": "CC-BY-4.0",
"access_right": "open",
"creators": [
{
"name": "Doe, Jane",
"orcid": "0000-0000-0000-0000",
"affiliation": "University of Example"
}
],
"contributors": [
{
"name": "Roe, Richard",
"type": "Editor",
"orcid": "0000-0000-0000-0001"
},
{
"name": "<WG name>",
"type": "WorkPackageLeader"
}
],
"communities": [{ "identifier": "cfde-rfcs" }],
"grants": [
{ "id": "<U24 award number>" },
{ "id": "<U54 award number>" }
],
"keywords": ["common fund data ecosystem", "data standards"],
"subjects": [
{
"term": "Data sharing",
"identifier": "http://edamontology.org/topic_XXXX",
"scheme": "EDAM"
}
],
"related_identifiers": [
{ "relation": "isDocumentedBy",
"identifier": "https://github.com/<org>/cfde-rfcs/tree/main/0007-some-topic",
"resource_type": "software" },
{ "relation": "isVersionOf",
"identifier": "10.5281/zenodo.CONCEPT" },
{ "relation": "isPartOf",
"identifier": "10.5281/zenodo.SERIES_RECORD" },
{ "relation": "references",
"identifier": "10.5281/zenodo.YYYYYYY" },
{ "relation": "isNewVersionOf",
"identifier": "10.5281/zenodo.PRIOR_RFC" },
{ "relation": "isDescribedBy",
"identifier": "https://fairsharing.org/bsg-sXXXXXX" }
],
"notes": "Status: Accepted. Supersedes RFC-0003. See VERSIONING.md for policy."
}related_identifiers is the single most important FAIR field here. Every entry
is a discovery edge in the scholarly graph. Use it aggressively for:
provenance (isDocumentedBy → GitHub source), the version chain
(isVersionOf / isNewVersionOf / isPreviousVersionOf), series membership
(isPartOf → the series record), inter-RFC citation (references /
isReferencedBy), and links to any FAIRsharing record (isDescribedBy).
The RFC body carries YAML front-matter that drives both the index generator and an
embedded schema.org block in the rendered HTML <head>. This is what makes
Google Dataset Search and Scholar see structured metadata — the cheapest
reach-new-users lever once the other two surfaces exist.
---
rfc: 0007
title: "<Title>"
status: Accepted # Draft | In Review | Accepted | Superseded | Withdrawn
working-group: "<WG name>"
authors: ["Jane Doe", "Richard Roe"]
created: 2025-11-01
version: "1.0.0"
doi: "10.5281/zenodo.XXXXXXX"
supersedes: []
superseded-by: []
---Rendered into the page head as schema.org/TechArticle:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"identifier": "https://doi.org/10.5281/zenodo.XXXXXXX",
"headline": "CFDE RFC-0007: <Title>",
"author": [{ "@type": "Person", "name": "Jane Doe",
"identifier": "https://orcid.org/0000-0000-0000-0000" }],
"datePublished": "2026-01-15",
"version": "1.0.0",
"license": "https://creativecommons.org/licenses/by/4.0/",
"isPartOf": { "@type": "CreativeWorkSeries", "name": "CFDE RFCs" },
"funding": "<U24 / U54 award numbers>",
"sameAs": [
"https://github.com/<org>/cfde-rfcs/tree/main/0007-some-topic",
"https://doi.org/10.5281/zenodo.XXXXXXX",
"https://fairsharing.org/bsg-sXXXXXX"
]
}
</script>State this explicitly in VERSIONING.md so it is itself machine- and
human-discoverable.
Zenodo provides two DOIs per record:
- a concept DOI that always resolves to the latest version — use this for "cite the RFC" (in the README, the index, general references);
- a version DOI that resolves to one exact, frozen text — use this for "cite exactly this text" (in reproducibility-sensitive citations).
Both belong in the metadata: the concept DOI in CITATION.cff doi:, the version
DOI minted fresh on each tagged deposition.
MAJOR— substantive change to the proposal's meaning or recommendations.MINOR— added clarification or non-substantive expansion.PATCH— typo / formatting / link fixes.
Each MAJOR/MINOR bump is a new Zenodo version (new version DOI, same concept
DOI). PATCH fixes may be batched.
Draft → In Review → Accepted → Superseded | Withdrawn
Surface status in both the page front-matter and the Zenodo notes/version,
so it is machine-discoverable rather than only visible on a web page.
DataCite relationships are directional, so populate both sides. When RFC-0007 supersedes RFC-0003:
- on 0007:
isNewVersionOf→ 0003 (and front-mattersupersedes: [0003]); - on 0003:
isPreviousVersionOf→ 0007 (andsuperseded-by: [0007]), re-deposited as a new version so the link is live.
This makes the graph traversable from either node.
Create one Zenodo record (or use the Community landing page) describing the RFC
series as a whole, modeled as a schema.org/CreativeWorkSeries /
Collection. Each RFC points to it with isPartOf. This gives the series its
own identity and a single citable entry point for "the CFDE RFC process."
Neither FAIRsharing nor re3data is a document host — they catalog standards, databases, data policies (FAIRsharing) and research data repositories (re3data). An RFC by itself is not a registrable object in either.
However, for the subset of RFCs whose content defines a registrable artifact, register that artifact and link the RFC as its documentation:
- RFC proposes/defines a standard (schema, reporting checklist, terminology,
identifier scheme) → register the standard in FAIRsharing; link the RFC DOI via
isDescribedBy/documents. - RFC describes/governs a data resource (repository, knowledgebase, portal) → register in FAIRsharing (database) and/or re3data (repository).
- RFC is a data policy → register in the FAIRsharing policy registry.
This is the substitute for the preprint lever (preprint servers are increasingly restrictive about non-study, "RFC-shaped" content). The registries are built for exactly the cross-domain discovery we want — they let a reader arrive from a neighboring field via the standard, the repository, or the policy, and find the RFC behind it. FAIRsharing records also carry their own persistent, citable identifiers, so a registration is complementary to (not redundant with) the Zenodo DOI.
At 5–10 RFCs/year with only a fraction producing registrable artifacts, this is a small, occasional curatorial task, not a per-RFC requirement.
- Rust RFCs —
https://github.com/rust-lang/rfcs— the canonical monorepo model: each RFC is a Markdown file added via PR; the repo is both proposal system and permanent design record. Rendered RFC Book:https://rust-lang.github.io/rfcs/. (Rust does not mint DOIs — that is the piece we add.) - Rust RFC process text —
https://rust-lang.github.io/rfcs/0002-rfc-process.html— the process itself, written as RFC-0002; a good template for ourCONTRIBUTING.md. - IETF RFCs —
https://www.rfc-editor.org/— the original "RFC" model; a numbered, permanent, individually citable series with a controlled status vocabulary (Proposed Standard, Draft Standard, Obsoleted-by/Updates relations) that directly inspired our status + supersession design. - Kubernetes KEPs —
https://github.com/kubernetes/enhancements— a monorepo of per-enhancement directories (keps/NNNN-title/), each with structured YAML metadata and a lifecycle status — the closest structural analog to the per-RFC-directory layout proposed here. - Zenodo GitHub integration & versioning —
https://help.zenodo.org/docs/— concept-DOI vs. version-DOI semantics and the deposition API used by thepublish-rfc.ymlworkflow. - FAIRsharing —
https://fairsharing.org/— registry of standards, databases, and policies, for Part 4 amplification. - re3data —
https://www.re3data.org/— registry of research data repositories.
- One monorepo (
cfde-rfcs) for drafting, review, comment (Issues/Discussions), and a rendered GitHub Pages RFC Book — following the Rust/KEP model. - One independently versioned Zenodo record per RFC, deposited by an explicit per-RFC git tag + CI job — not the repo-granular release hook — gathered under a single Zenodo Community.
- Three consistent, cross-linked metadata surfaces —
CITATION.cff,.zenodo.json, and front-matter→JSON-LD — with ORCIDs, RORs, grant IDs, and an aggressively populatedrelated_identifiersgraph. - An explicit versioning policy — concept vs. version DOIs, semantic versioning, a controlled status vocabulary, reciprocal supersession links, and a series-level record.
- Selective FAIRsharing / re3data registration for the subset of RFCs that define a standard, data resource, or policy — the cross-domain "find new users" amplifier and the substitute for preprints.