Files
yvgude--lean-ctx/rust/tests/openapi_contract_up_to_date.rs
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

83 lines
2.8 KiB
Rust

//! Binds the public `OpenAPI` surface (`core::openapi::endpoints`) to the
//! Endpoints table in `docs/contracts/http-mcp-contract-v1.md`. Adding or
//! removing a public route must touch both, or this fails (EPIC 12.1).
use std::collections::BTreeSet;
use std::path::PathBuf;
/// Parse `(METHOD, /path)` pairs from the first markdown table under the
/// `## Endpoints` heading. Skips the header/separator rows and the `/*`
/// MCP fallback (it is not an `OpenAPI` path).
fn documented_pairs(doc: &str) -> BTreeSet<(String, String)> {
let mut out = BTreeSet::new();
let mut in_section = false;
for line in doc.lines() {
if line.starts_with("## ") {
if line.trim() == "## Endpoints" {
in_section = true;
continue;
} else if in_section {
break; // left the Endpoints section
}
}
if !in_section || !line.trim_start().starts_with('|') {
continue;
}
let cells: Vec<String> = line
.trim()
.trim_matches('|')
.split('|')
.map(|c| c.trim().to_string())
.collect();
if cells.len() < 2 {
continue;
}
let method = cells[0].to_uppercase();
let path = cells[1].trim_matches('`').trim().to_string();
if method == "METHOD" || method.starts_with("---") {
continue;
}
if !path.starts_with('/') || path.contains('*') {
continue; // header noise or the MCP fallback
}
out.insert((method, path));
}
out
}
#[test]
fn openapi_endpoints_match_contract_doc() {
let rust_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let repo_root = rust_dir.parent().unwrap_or(&rust_dir);
let doc_path = repo_root.join("docs/contracts/http-mcp-contract-v1.md");
let doc = match std::fs::read_to_string(&doc_path) {
Ok(c) => c,
Err(e) => {
assert!(
!repo_root.join("docs/contracts").exists(),
"missing HTTP/MCP contract at {}: {e}",
doc_path.display()
);
eprintln!("skipping: {} not present", doc_path.display());
return;
}
};
let documented = documented_pairs(&doc);
let code: BTreeSet<(String, String)> = lean_ctx::core::openapi::endpoints()
.iter()
.map(|e| (e.method.to_uppercase(), e.path.to_string()))
.collect();
assert_eq!(
code,
documented,
"OpenAPI inventory (core::openapi::endpoints) is out of sync with the \
Endpoints table in {}.\nin code only: {:?}\nin doc only: {:?}",
doc_path.display(),
code.difference(&documented).collect::<Vec<_>>(),
documented.difference(&code).collect::<Vec<_>>(),
);
}