1use std::collections::BTreeMap;
2
3pub const MCP_MANIFEST_SCHEMA_VERSION: u32 = 1;
5pub const CONTEXT_PROOF_V1_SCHEMA_VERSION: u32 = 1;
6pub const CONTEXT_IR_V1_SCHEMA_VERSION: u32 = 1;
7pub const INTENT_ROUTE_V1_SCHEMA_VERSION: u32 = 1;
8pub const DEGRADATION_POLICY_V1_SCHEMA_VERSION: u32 = 1;
9pub const WORKFLOW_EVIDENCE_LEDGER_V1_SCHEMA_VERSION: u32 = 1;
10pub const AUTONOMY_DRIVERS_V1_SCHEMA_VERSION: u32 = 1;
11pub const TOKENIZER_TRANSLATION_DRIVER_V1_SCHEMA_VERSION: u32 = 1;
12pub const ATTENTION_LAYOUT_DRIVER_V1_SCHEMA_VERSION: u32 = 1;
13pub const VERIFICATION_OBSERVABILITY_V1_SCHEMA_VERSION: u32 = 1;
14pub const HANDOFF_LEDGER_V1_SCHEMA_VERSION: u32 = 1;
15pub const HANDOFF_TRANSFER_BUNDLE_V1_SCHEMA_VERSION: u32 = 1;
16pub const CCP_SESSION_BUNDLE_V1_SCHEMA_VERSION: u32 = 1;
17pub const KNOWLEDGE_POLICY_V1_SCHEMA_VERSION: u32 = 1;
18pub const GRAPH_REPRODUCIBILITY_V1_SCHEMA_VERSION: u32 = 1;
19pub const A2A_SNAPSHOT_V1_SCHEMA_VERSION: u32 = 1;
20pub const MEMORY_BOUNDARY_V1_SCHEMA_VERSION: u32 = 1;
21pub const GOTCHAS_REMINDERS_V1_SCHEMA_VERSION: u32 = 1;
22pub const PROVIDER_FRAMEWORK_V1_SCHEMA_VERSION: u32 = 1;
23pub const CONTEXT_PACKAGE_V1_SCHEMA_VERSION: u32 = 1;
24pub const CONTEXT_PACKAGE_V2_SCHEMA_VERSION: u32 = 2;
25pub const CONTEXT_SNAPSHOT_V1_SCHEMA_VERSION: u32 = 1;
26
27pub const PACKAGE_EXTENSION: &str = "ctxpkg";
28pub const LEGACY_PACKAGE_EXTENSION: &str = "lctxpkg";
29pub const MAX_PACKAGE_FILE_BYTES: u64 = 10 * 1024 * 1024; pub fn is_package_file(path: &std::path::Path) -> bool {
32 path.extension()
33 .and_then(|e| e.to_str())
34 .is_some_and(|ext| ext == PACKAGE_EXTENSION || ext == LEGACY_PACKAGE_EXTENSION)
35}
36
37pub fn default_package_filename(name: &str, version: &str) -> String {
38 format!("{name}-{version}.{PACKAGE_EXTENSION}")
39}
40
41pub const HTTP_MCP_CONTRACT_VERSION: u32 = 1;
43pub const TEAM_SERVER_CONTRACT_VERSION: u32 = 1;
44pub const CAPABILITIES_CONTRACT_VERSION: u32 = 1;
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum ContractStatus {
58 Frozen,
59 Stable,
60 Experimental,
61}
62
63impl ContractStatus {
64 pub fn as_str(self) -> &'static str {
65 match self {
66 ContractStatus::Frozen => "frozen",
67 ContractStatus::Stable => "stable",
68 ContractStatus::Experimental => "experimental",
69 }
70 }
71}
72
73pub struct ContractDoc {
76 pub id: &'static str,
78 pub doc_file: &'static str,
80 pub version: u32,
81 pub status: ContractStatus,
82}
83
84pub fn contract_docs() -> Vec<ContractDoc> {
89 use ContractStatus::{Experimental, Frozen, Stable};
90 let doc = |id, doc_file, version, status| ContractDoc {
91 id,
92 doc_file,
93 version,
94 status,
95 };
96 vec![
97 doc("http-mcp", "http-mcp-contract-v1.md", 1, Frozen),
99 doc("team-server", "team-server-contract-v1.md", 1, Frozen),
100 doc("context-ir", "context-ir-v1.md", 1, Frozen),
101 doc(
102 "local-free-invariant",
103 "local-free-invariant-v1.md",
104 1,
105 Frozen,
106 ),
107 doc(
108 "oss-plane-separation",
109 "oss-plane-separation-v1.md",
110 1,
111 Frozen,
112 ),
113 doc("billing-plane", "billing-plane-v1.md", 1, Frozen),
114 doc("wasm-abi", "wasm-abi-v1.md", 1, Frozen),
115 doc("delivery-manifest", "delivery-manifest-v1.md", 1, Frozen),
119 doc(
120 "deployment-rehearsal",
121 "deployment-rehearsal-v1.md",
122 1,
123 Frozen,
124 ),
125 doc(
126 "release-key-rotation",
127 "release-key-rotation-v1.md",
128 1,
129 Frozen,
130 ),
131 doc("capabilities", "capabilities-contract-v1.md", 1, Stable),
136 doc("billing-plane-v2", "billing-plane-v2.md", 2, Stable),
137 doc("billing-plane-v3", "billing-plane-v3.md", 3, Stable),
139 doc("evidence-bundle", "evidence-bundle-v1.md", 1, Stable),
141 doc(
143 "settlement-evidence",
144 "settlement-evidence-v2.md",
145 2,
146 Stable,
147 ),
148 doc("team-server-v2", "team-server-contract-v2.md", 2, Stable),
150 doc("a2a", "a2a-contract-v1.md", 1, Stable),
151 doc(
152 "attention-layout-driver",
153 "attention-layout-driver-v1.md",
154 1,
155 Stable,
156 ),
157 doc("autonomy-drivers", "autonomy-drivers-v1.md", 1, Stable),
158 doc("ccp-session-bundle", "ccp-session-bundle-v1.md", 1, Stable),
159 doc("conformance", "conformance-v1.md", 1, Stable),
160 doc(
161 "ocla-verifier-conformance",
162 "ocla-verifier-conformance-v1.md",
163 1,
164 Stable,
165 ),
166 doc("degradation-policy", "degradation-policy-v1.md", 1, Stable),
167 doc("extension-trust", "extension-trust-v1.md", 1, Stable),
168 doc("extractors", "extractors-v1.md", 1, Stable),
169 doc("contracts-readme", "README.md", 1, Stable),
170 doc("deprecation-policy", "DEPRECATION.md", 1, Stable),
171 doc("audit-schedule", "audit-schedule-v1.md", 1, Stable),
172 doc("branch-protection", "branch-protection-v1.md", 1, Stable),
173 doc(
174 "certification-levels",
175 "certification-levels-v1.md",
176 1,
177 Stable,
178 ),
179 doc("release-integrity", "release-integrity-v1.md", 1, Stable),
180 doc(
181 "gotchas-reminders",
182 "gotchas-reminders-contract-v1.md",
183 1,
184 Stable,
185 ),
186 doc(
187 "graph-reproducibility",
188 "graph-reproducibility-contract-v1.md",
189 1,
190 Stable,
191 ),
192 doc(
193 "handoff-transfer-bundle",
194 "handoff-transfer-bundle-v1.md",
195 1,
196 Stable,
197 ),
198 doc("intent-route", "intent-route-v1.md", 1, Stable),
199 doc(
200 "knowledge-policy",
201 "knowledge-policy-contract-v1.md",
202 1,
203 Stable,
204 ),
205 doc(
206 "memory-boundary",
207 "memory-boundary-contract-v1.md",
208 1,
209 Stable,
210 ),
211 doc("persona-spec", "persona-spec-v1.md", 1, Stable),
212 doc(
213 "provider-framework",
214 "provider-framework-contract-v1.md",
215 1,
216 Stable,
217 ),
218 doc(
219 "tokenizer-translation-driver",
220 "tokenizer-translation-driver-v1.md",
221 1,
222 Stable,
223 ),
224 doc(
225 "workflow-evidence-ledger",
226 "workflow-evidence-ledger-v1.md",
227 1,
228 Stable,
229 ),
230 doc("wrapped-permalink", "wrapped-permalink-v1.md", 1, Stable),
231 doc("addon-manifest", "addon-manifest-v1.md", 1, Stable),
234 doc(
238 "context-candidate-admission",
239 "context-candidate-admission-v1.md",
240 1,
241 Experimental,
242 ),
243 doc(
244 "multi-agent-efficiency-benchmark",
245 "multi-agent-efficiency-benchmark-v1.md",
246 1,
247 Experimental,
248 ),
249 doc(
252 "test-deployment-evidence",
253 "test-deployment-evidence-v1.md",
254 1,
255 Experimental,
256 ),
257 doc(
260 "ocla-config-tuning",
261 "ocla-config-tuning-v2.md",
262 2,
263 Experimental,
264 ),
265 doc(
266 "hosted-personal-index",
267 "hosted-personal-index-v1.md",
268 1,
269 Experimental,
270 ),
271 doc(
272 "personal-cloud-encryption",
273 "personal-cloud-encryption-v1.md",
274 1,
275 Experimental,
276 ),
277 doc(
280 "context-policy-packs",
281 "context-policy-packs-v1.md",
282 1,
283 Experimental,
284 ),
285 doc("device-overview", "device-overview-v1.md", 1, Experimental),
286 doc("email-digest", "email-digest-v1.md", 1, Experimental),
287 doc("org-audit-log", "org-audit-log-v1.md", 1, Experimental),
288 doc("org-sso-oidc", "org-sso-oidc-v1.md", 1, Experimental),
289 doc("quality-loop", "quality-loop-v1.md", 1, Experimental),
291 doc("edit-metering", "edit-metering-v1.md", 1, Experimental),
293 doc("ctxpkg-registry", "ctxpkg-registry-v1.md", 1, Experimental),
295 doc(
298 "context-snapshot",
299 "context-snapshot-v1.md",
300 1,
301 Experimental,
302 ),
303 doc(
304 "team-invite-links",
305 "team-invite-links-v1.md",
306 1,
307 Experimental,
308 ),
309 doc("org-policy", "org-policy-v1.md", 1, Experimental),
314 doc(
315 "compliance-report",
316 "compliance-report-v1.md",
317 1,
318 Experimental,
319 ),
320 doc("pillar-boundaries", "pillar-boundaries-v1.md", 1, Stable),
321 doc(
324 "logical-session-presence",
325 "logical-session-presence-v1.md",
326 1,
327 Experimental,
328 ),
329 doc(
330 "tokenizer-calibration",
331 "tokenizer-calibration-v1.md",
332 1,
333 Experimental,
334 ),
335 ]
336}
337
338pub fn status_kv() -> BTreeMap<&'static str, &'static str> {
341 contract_docs()
342 .into_iter()
343 .map(|d| (d.id, d.status.as_str()))
344 .collect()
345}
346
347pub fn versions_kv() -> BTreeMap<&'static str, u32> {
348 BTreeMap::from([
349 (
350 "leanctx.contract.mcp_manifest.schema_version",
351 MCP_MANIFEST_SCHEMA_VERSION,
352 ),
353 (
354 "leanctx.contract.context_proof_v1.schema_version",
355 CONTEXT_PROOF_V1_SCHEMA_VERSION,
356 ),
357 (
358 "leanctx.contract.context_ir_v1.schema_version",
359 CONTEXT_IR_V1_SCHEMA_VERSION,
360 ),
361 (
362 "leanctx.contract.intent_route_v1.schema_version",
363 INTENT_ROUTE_V1_SCHEMA_VERSION,
364 ),
365 (
366 "leanctx.contract.degradation_policy_v1.schema_version",
367 DEGRADATION_POLICY_V1_SCHEMA_VERSION,
368 ),
369 (
370 "leanctx.contract.workflow_evidence_ledger_v1.schema_version",
371 WORKFLOW_EVIDENCE_LEDGER_V1_SCHEMA_VERSION,
372 ),
373 (
374 "leanctx.contract.autonomy_drivers_v1.schema_version",
375 AUTONOMY_DRIVERS_V1_SCHEMA_VERSION,
376 ),
377 (
378 "leanctx.contract.tokenizer_translation_driver_v1.schema_version",
379 TOKENIZER_TRANSLATION_DRIVER_V1_SCHEMA_VERSION,
380 ),
381 (
382 "leanctx.contract.attention_layout_driver_v1.schema_version",
383 ATTENTION_LAYOUT_DRIVER_V1_SCHEMA_VERSION,
384 ),
385 (
386 "leanctx.contract.verification_observability_v1.schema_version",
387 VERIFICATION_OBSERVABILITY_V1_SCHEMA_VERSION,
388 ),
389 (
390 "leanctx.contract.handoff_ledger_v1.schema_version",
391 HANDOFF_LEDGER_V1_SCHEMA_VERSION,
392 ),
393 (
394 "leanctx.contract.handoff_transfer_bundle_v1.schema_version",
395 HANDOFF_TRANSFER_BUNDLE_V1_SCHEMA_VERSION,
396 ),
397 (
398 "leanctx.contract.ccp_session_bundle_v1.schema_version",
399 CCP_SESSION_BUNDLE_V1_SCHEMA_VERSION,
400 ),
401 (
402 "leanctx.contract.knowledge_policy_v1.schema_version",
403 KNOWLEDGE_POLICY_V1_SCHEMA_VERSION,
404 ),
405 (
406 "leanctx.contract.graph_reproducibility_v1.schema_version",
407 GRAPH_REPRODUCIBILITY_V1_SCHEMA_VERSION,
408 ),
409 (
410 "leanctx.contract.a2a_snapshot_v1.schema_version",
411 A2A_SNAPSHOT_V1_SCHEMA_VERSION,
412 ),
413 (
414 "leanctx.contract.memory_boundary_v1.schema_version",
415 MEMORY_BOUNDARY_V1_SCHEMA_VERSION,
416 ),
417 (
418 "leanctx.contract.gotchas_reminders_v1.schema_version",
419 GOTCHAS_REMINDERS_V1_SCHEMA_VERSION,
420 ),
421 (
422 "leanctx.contract.provider_framework_v1.schema_version",
423 PROVIDER_FRAMEWORK_V1_SCHEMA_VERSION,
424 ),
425 (
426 "leanctx.contract.context_package_v1.schema_version",
427 CONTEXT_PACKAGE_V1_SCHEMA_VERSION,
428 ),
429 (
430 "leanctx.contract.context_package_v2.schema_version",
431 CONTEXT_PACKAGE_V2_SCHEMA_VERSION,
432 ),
433 (
434 "leanctx.contract.context_snapshot_v1.schema_version",
435 CONTEXT_SNAPSHOT_V1_SCHEMA_VERSION,
436 ),
437 (
438 "leanctx.contract.http_mcp.contract_version",
439 HTTP_MCP_CONTRACT_VERSION,
440 ),
441 (
442 "leanctx.contract.team_server.contract_version",
443 TEAM_SERVER_CONTRACT_VERSION,
444 ),
445 (
446 "leanctx.contract.capabilities.contract_version",
447 CAPABILITIES_CONTRACT_VERSION,
448 ),
449 ])
450}
451
452#[cfg(test)]
453mod tests {
454 use super::*;
455
456 #[test]
457 fn contract_docs_have_unique_ids_and_files() {
458 let docs = contract_docs();
459 let mut ids: Vec<_> = docs.iter().map(|d| d.id).collect();
460 let mut files: Vec<_> = docs.iter().map(|d| d.doc_file).collect();
461 ids.sort_unstable();
462 files.sort_unstable();
463 let unique_ids: std::collections::BTreeSet<_> = ids.iter().collect();
464 let unique_files: std::collections::BTreeSet<_> = files.iter().collect();
465 assert_eq!(unique_ids.len(), docs.len(), "duplicate contract id");
466 assert_eq!(unique_files.len(), docs.len(), "duplicate doc file");
467 }
468
469 #[test]
470 fn frozen_set_covers_the_platform_promises() {
471 let docs = contract_docs();
475 for id in [
476 "http-mcp",
477 "team-server",
478 "context-ir",
479 "local-free-invariant",
480 "oss-plane-separation",
481 "billing-plane",
482 "wasm-abi",
483 "delivery-manifest",
484 "deployment-rehearsal",
485 "release-key-rotation",
486 ] {
487 let entry = docs.iter().find(|d| d.id == id).expect("listed");
488 assert_eq!(
489 entry.status,
490 ContractStatus::Frozen,
491 "{id} must stay frozen"
492 );
493 }
494 }
495
496 #[test]
497 fn status_kv_matches_docs() {
498 let kv = status_kv();
499 assert_eq!(kv.len(), contract_docs().len());
500 assert_eq!(kv["http-mcp"], "frozen");
501 assert_eq!(kv["hosted-personal-index"], "experimental");
502 assert_eq!(kv["personal-cloud-encryption"], "experimental");
503 assert_eq!(kv["context-candidate-admission"], "experimental");
504 assert_eq!(kv["multi-agent-efficiency-benchmark"], "experimental");
505 assert_eq!(kv["test-deployment-evidence"], "experimental");
506 }
507
508 #[test]
509 fn doc_files_follow_versioned_naming() {
510 for d in contract_docs() {
514 if d.doc_file == "README.md" || d.doc_file == "DEPRECATION.md" {
515 continue;
516 }
517 assert!(
518 d.doc_file.ends_with(&format!("-v{}.md", d.version)),
519 "{} must end in -v{}.md",
520 d.doc_file,
521 d.version
522 );
523 }
524 }
525}