Parse YAML/TOML frontmatter from Markdown bytes into kebab_core::Metadata, with auto-derive defaults and unknown-key preservation in metadata.user.
Why now / why this size
Frontmatter is small but contractually load-bearing (Q9 spec). Isolating it from block parsing keeps both halves of kebab-parse-md simple and lets us reach 100% test coverage on the rules in design §0 Q9.
Allowed dependencies
kebab-core
kebab-parse-types (provides shared Warning + WarningKind per design §3.7b)
serde
serde_yaml (or yaml-rust2) for YAML
toml for TOML
time
lingua (lang auto-detect — accept feature-gate if heavy)
thiserror
Forbidden dependencies
kebab-store-*, kebab-llm*, kebab-rag, kebab-embed*, kebab-search, kebab-tui, kebab-desktop, kebab-source-fs, kebab-chunk, kebab-normalize, pulldown-cmark (block parser is a sibling task)
Warning / WarningKind come from kebab-parse-types (shared with p1-3 blocks parser and downstream kebab-normalize). FrontmatterSpan is crate-internal; if any new public type is needed, STOP and update the frozen design doc first.
Behavior contract
All Metadata fields are optional in input. Missing fields populated per design §0 Q9 derive table:
title ← first H1 (from BodyHints.first_h1) → filename without extension if no H1.
lang ← lingua auto-detect on first 4 KB of body → fallback BodyHints.fallback_lang or "und".
created_at / updated_at ← BodyHints.fs_ctime / fs_mtime if missing.