zuka
zuka/src/api/openapi.rs

worklyn / zukapublic

Agent-first git hosting. One Rust binary: git over HTTP and SSH, a REST API, MCP, CI, and multi-tenant isolation.

Get a copy: git clone https://zuka.worklyn.com/worklyn/zuka.git
zuka/src/api/openapi.rs
RSopenapi.rs4.3 KBDownload
1// The OpenAPI document, served at `/openapi.json` and committed as `openapi.json`.
2//
3// Embedded with `include_str!` so the served document and the committed file cannot
4// drift: there is one artifact.
5//
6// The coverage test below checks a hand-maintained list, so it catches a route that
7// is documented and removed, not one that is added and never documented. Deriving
8// the list from the router would need a route table the router does not have.
9
10/// The committed OpenAPI 3.1 document.
11pub const DOCUMENT: &str = include_str!("../../openapi.json");
12
13#[cfg(test)]
14mod tests {
15 use super::*;
16
17 fn document() -> serde_json::Value {
18 serde_json::from_str(DOCUMENT).expect("openapi.json must be valid JSON")
19 }
20
21 #[test]
22 fn is_a_valid_openapi_3_1_document() {
23 let doc = document();
24 assert_eq!(doc["openapi"], "3.1.0");
25 assert!(doc["info"]["title"].is_string());
26 assert!(doc["info"]["version"].is_string());
27 assert!(doc["paths"].is_object());
28 }
29
30 #[test]
31 fn documents_every_route_the_router_serves() {
32 let doc = document();
33 let paths = doc["paths"].as_object().expect("paths is an object");
34
35 for route in [
36 "/healthz",
37 "/openapi.json",
38 "/v1/account",
39 "/v1/keys",
40 "/v1/keys/{id}",
41 "/v1/repos",
42 "/v1/repos/{account}/{repo}",
43 "/v1/repos/{account}/{repo}/refs",
44 "/v1/repos/{account}/{repo}/tree/{path}",
45 "/v1/repos/{account}/{repo}/raw/{path}",
46 "/v1/repos/{account}/{repo}/commits",
47 "/v1/repos/{account}/{repo}/commits/{sha}",
48 "/v1/repos/{account}/{repo}/compare",
49 "/v1/repos/{account}/{repo}/search",
50 "/v1/repos/{account}/{repo}/blame/{path}",
51 "/mcp",
52 "/v1/repos/{account}/{repo}/runs",
53 "/v1/repos/{account}/{repo}/runs/{id}",
54 "/v1/repos/{account}/{repo}/runs/{id}/logs",
55 "/{account}/{repo}.git/info/refs",
56 ] {
57 assert!(
58 paths.contains_key(route),
59 "{route} is served but undocumented"
60 );
61 }
62 }
63
64 #[test]
65 fn the_document_identifies_the_running_crate() {
66 let doc = document();
67 assert_eq!(
68 doc["info"]["title"],
69 crate::brand::NAME,
70 "the served document must name the service that serves it"
71 );
72
73 // Major and minor only. This describes the API contract, and the contract
74 // does not change because CI produced another build — the patch component
75 // is the build number, which grows on every run. Comparing the whole string
76 // would mean editing this file on every commit to say nothing new.
77 let api_version = doc["info"]["version"].as_str().unwrap_or_default();
78 let series = |v: &str| v.split('.').take(2).collect::<Vec<_>>().join(".");
79 assert_eq!(
80 series(api_version),
81 series(crate::brand::VERSION),
82 "the documented API series must match the running one"
83 );
84 }
85
86 #[test]
87 fn quota_and_rate_limit_problems_are_documented() {
88 let doc = document();
89 let examples = doc["components"]["schemas"]["Problem"]["properties"]["type"]["examples"]
90 .as_array()
91 .expect("problem types are enumerated")
92 .iter()
93 .filter_map(|v| v.as_str())
94 .collect::<Vec<_>>()
95 .join(" ");
96 assert!(examples.contains("quota-exceeded"));
97 assert!(examples.contains("rate-limited"));
98 }
99
100 #[test]
101 fn every_operation_declares_its_security_except_the_public_ones() {
102 let doc = document();
103 let public = ["/healthz", "/openapi.json"];
104
105 for (path, item) in doc["paths"].as_object().unwrap() {
106 for (method, operation) in item.as_object().unwrap() {
107 if method == "parameters" {
108 continue;
109 }
110 let declared = operation.get("security").is_some();
111 if public.contains(&path.as_str()) {
112 assert!(!declared, "{path} {method} is public but declares security");
113 } else {
114 assert!(declared, "{path} {method} does not declare security");
115 }
116 }
117 }
118 }
119}