"""Read-only rendering of `specs/policies/`/`specs/profiles/` markdown files for the Control Plane (WP-0015-T03). Server-side markdown -> HTML at request time, deliberately not a static build pipeline (unlike state-hub's Observable Framework Reference section, confirmed materially heavier during WP-0012-T03) -- this repo's existing lightweight FastAPI+Jinja2 stack needs nothing more than a small markdown library for six profile pages and one policy page. """ from __future__ import annotations from pathlib import Path from typing import Any import markdown import yaml _SPECS_DIR = Path(__file__).resolve().parents[3] / "specs" # kind -> subdirectory name under specs/. Only these two exist today # (WP-0015-T02); a third kind (e.g. "calculators") can be added here if # a future workplan gives calculators their own reference route. REFERENCE_KINDS = frozenset({"policies", "profiles"}) def load_reference_doc(kind: str, slug: str) -> tuple[str, dict[str, Any]] | None: """Return (rendered_html, frontmatter) for one spec file, or None if `kind` is unknown or no matching file exists. Read-only: there is no corresponding write path anywhere in this module.""" if kind not in REFERENCE_KINDS: return None path = _SPECS_DIR / kind / f"{slug}.md" if not path.is_file(): return None raw = path.read_text(encoding="utf-8") frontmatter: dict[str, Any] = {} if raw.startswith("---\n"): end = raw.find("\n---\n", 4) if end != -1: frontmatter = yaml.safe_load(raw[4:end]) or {} raw = raw[end + 5 :] html = markdown.markdown(raw) return html, frontmatter def policy_slug_from_id(policy_id: str) -> str: """`trsl:policy:linear-longstop-v0@1.0` -> `linear-longstop-v0`.""" name = policy_id.split(":")[-1] return name.split("@")[0] def extension_slug_from_id(extension_id: str) -> str: """`trsl:extension:development-license@1.0` -> `development-license`.""" name = extension_id.split(":")[-1] return name.split("@")[0]