okf_core/lib.rs
1//! # okf-core: the Open Knowledge Format, in pure Rust
2//!
3//! A pure-Rust implementation of the [Open Knowledge Format (OKF)
4//! v0.2][spec], Google's open, human- and agent-friendly format for
5//! representing knowledge as a directory of markdown files with YAML
6//! frontmatter.
7//!
8//! OKF is intentionally minimal ("if you can `cat` a file, you can read OKF; if
9//! you can `git clone` a repo, you can ship it"), so this crate implements it
10//! with the standard library alone: its own [YAML-subset parser](yaml), a
11//! markdown [link scanner](links), and a directory walker. The companion `okf` crate re-exports this
12//! entire library and ships the `okf` command-line tool.
13//!
14//! ## Model
15//!
16//! - A [`Bundle`] is a directory tree of markdown files.
17//! - A [`Concept`] is one markdown [`Document`] = YAML [`Frontmatter`] + body.
18//! - A [`ConceptId`] is a concept's path within the bundle, minus `.md`.
19//! - Concepts relate via markdown [`links`]; the bundle exposes the
20//! resulting graph and backlinks.
21//! - `index.md` directory listings are generated by [`index`].
22//! - `log.md` histories are parsed by [`log`].
23//! - Conformance checking and linting live in the companion
24//! [`okf-validator`](https://docs.rs/okf-validator) crate.
25//!
26//! ## What v0.2 adds
27//!
28//! v0.2 makes provenance, trust, lifecycle, and attestation first-class. Every
29//! one of the new keys is optional, and absence is meaningful rather than
30//! invalid, so a v0.1 document is still a conformant v0.2 document.
31//!
32//! | Concern | Frontmatter | Module |
33//! |-------------|----------------------------------------------------------------|-----------------|
34//! | Provenance | `sources`, `usage_window` | [`provenance`] |
35//! | Trust | `generated`, `verified`, trust tiers | [`trust`] |
36//! | Lifecycle | `status`, `stale_after` | [`trust`] |
37//! | Identity | the actor convention | [`actor`] |
38//! | Attestation | `runtime`, `parameters`, `computation`, `executor`, `attester` | [`computation`] |
39//! | Attribution | `[^label]` footnotes keyed to `sources[].id` | [`footnotes`] |
40//!
41//! Two v0.1 constructs are superseded but still readable, since a v0.2
42//! consumer is expected to handle v0.1 bundles: `timestamp` gives way to
43//! `generated.at` (see [`Frontmatter::content_changed_at`]), and the body
44//! `# Citations` list gives way to `sources` (see [`Document::citations`]).
45//!
46//! ## Example
47//!
48//! ```no_run
49//! use okf_core::{Bundle, ConceptId};
50//!
51//! let bundle = Bundle::load("./my_bundle")?;
52//! println!("{} concepts", bundle.len());
53//!
54//! let id = ConceptId::parse("tables/orders")?;
55//! for link in bundle.links_from(&id) {
56//! println!("{} -> {} (exists: {})", id, link.target, link.exists);
57//! }
58//! # Ok::<(), Box<dyn std::error::Error>>(())
59//! ```
60//!
61//! Reading a concept's trust signals:
62//!
63//! ```
64//! use okf_core::{Document, TrustTier};
65//!
66//! let doc = Document::parse(
67//! "---\n\
68//! type: Metric\n\
69//! title: Revenue\n\
70//! status: stable\n\
71//! generated: { by: reference_agent/gemini-2.5-pro, at: 2026-06-20T22:53:05Z }\n\
72//! verified: { by: human:walter, at: 2026-06-25T09:00:00Z }\n\
73//! stale_after: 2026-12-31\n\
74//! ---\n\n\
75//! # Definition\n",
76//! )
77//! .unwrap();
78//!
79//! // A bare `verified` mapping counts as a one-element list.
80//! assert_eq!(doc.frontmatter.verified().len(), 1);
81//! assert_eq!(doc.frontmatter.trust_tier(), TrustTier::HumanReviewed);
82//! assert_eq!(doc.frontmatter.status().to_string(), "stable");
83//! ```
84//!
85//! [spec]: https://github.com/GoogleCloudPlatform/open-knowledge-format/blob/main/SPEC.md
86
87#![forbid(unsafe_code)]
88#![warn(missing_docs)]
89// Pedantic and nursery lints keep the published crate tidy; the few cases
90// where a lint is genuinely wrong for this codebase are silenced inline with a
91// justification.
92#![warn(clippy::pedantic, clippy::nursery)]
93
94pub mod actor;
95pub mod bundle;
96pub mod computation;
97pub mod concept_id;
98pub mod date;
99pub mod diff;
100pub mod document;
101pub mod error;
102pub mod fix;
103pub mod footnotes;
104pub mod frontmatter;
105pub mod index;
106pub mod links;
107pub mod log;
108pub mod markdown;
109pub mod provenance;
110pub mod refactor;
111pub mod scaffold;
112pub mod trust;
113pub mod yaml;
114
115/// The OKF specification version this crate implements.
116pub const OKF_VERSION: &str = "0.2";
117
118/// Specification versions this crate can consume.
119///
120/// v0.2 is a minor bump over v0.1 with two documented supersessions,
121/// both of which this crate still reads, so a v0.1 bundle loads and
122/// validates without special handling.
123pub const SUPPORTED_OKF_VERSIONS: [&str; 2] = ["0.1", "0.2"];
124
125#[doc(inline)]
126pub use actor::{Actor, ActorKind, ParseActorKindError};
127#[doc(inline)]
128pub use bundle::{Bundle, Concept, RESERVED_FILENAMES, ResolvedLink, ResolvedSource};
129#[doc(inline)]
130pub use computation::{
131 ATTESTED_COMPUTATION_TYPE, AttestedComputation, Attester, ComputationSource, Executor,
132 InlineComputation, Parameter,
133};
134#[doc(inline)]
135pub use concept_id::{ConceptId, ConceptIdError};
136#[doc(inline)]
137pub use date::{Date, DateField, DateTime, DateTimeField};
138#[doc(inline)]
139pub use diff::{BundleDiff, FrontmatterChange, Rename, TrustChange, bundle_diff};
140#[doc(inline)]
141pub use document::Document;
142#[doc(inline)]
143pub use error::{BundleError, DocumentError};
144#[doc(inline)]
145pub use fix::{
146 BundleFixReport, FileFixReport, FixOptions, Remediation, RemediationKind, remediate_bundle,
147 remediate_document, remediate_file, remediate_log,
148};
149#[doc(inline)]
150pub use footnotes::{FootnoteDef, FootnoteRef};
151#[doc(inline)]
152pub use frontmatter::{
153 Frontmatter, KNOWN_FRONTMATTER_KEYS, LEGACY_FRONTMATTER_KEYS, PREFERRED_KEY_ORDER,
154 RECOMMENDED_FRONTMATTER_KEYS, REQUIRED_FRONTMATTER_KEYS,
155};
156#[doc(inline)]
157pub use links::{Citation, Link, LinkKind, ParseLinkKindError, field_path_candidates};
158#[doc(inline)]
159pub use log::{Log, LogDay, LogEntry, append_log_entry};
160#[doc(inline)]
161pub use markdown::{
162 LinkRewriteAction, MarkdownHeading, extract_headings, heading_slug, matches_heading,
163 parse_heading_line, rewrite_markdown_links,
164};
165#[doc(inline)]
166pub use provenance::{Attribution, ResourceKind, Source, UsageWindow};
167#[doc(inline)]
168pub use refactor::{
169 MergeOptions, MergeReport, MoveOptions, MoveReport, RefactorError, RemoveOptions, RemoveReport,
170 RenameSectionOptions, RenameSectionReport, SplitOptions, SplitReport, compute_relative_path,
171 merge_concepts, move_concept, rebase_relative_path, remove_concept, rename_section,
172 split_concept,
173};
174#[doc(inline)]
175pub use scaffold::{
176 BundleInitOptions, ConceptOptions, create_concept, default_author, init_bundle,
177};
178#[doc(inline)]
179pub use trust::{Generated, ParseTrustTierError, Status, TrustTier, Verification};
180#[doc(inline)]
181pub use yaml::{Mapping, Value};