1use serde::{Deserialize, Deserializer, Serialize};
6use std::collections::HashSet;
7use std::fmt;
8use thiserror::Error;
9
10pub const OLLAMA_CHAT_PATH: &str = "/api/chat";
11pub const OLLAMA_RELAY_ORIGIN: &str = "http://127.0.0.1:11434";
12pub const OLLAMA_CLOUD_ORIGIN: &str = "https://ollama.com";
13pub const OLLAMA_GLM_5_2_MODEL: &str = "glm-5.2";
14pub const OPENROUTER_ORIGIN: &str = "https://openrouter.ai";
15pub const OPENROUTER_CHAT_PATH: &str = "/api/v1/chat/completions";
16pub const DASHSCOPE_ORIGIN: &str = "https://dashscope-intl.aliyuncs.com";
17pub const DASHSCOPE_TOKEN_PLAN_ORIGIN: &str = "https://token-plan.ap-southeast-1.maas.aliyuncs.com";
22pub const DASHSCOPE_CHAT_PATH: &str = "/compatible-mode/v1/chat/completions";
23pub const XAI_ORIGIN: &str = "https://api.x.ai";
24pub const XAI_CHAT_PATH: &str = "/v1/chat/completions";
25pub const ZAI_ORIGIN: &str = "https://api.z.ai";
26pub const ZAI_CHAT_PATH: &str = "/api/paas/v4/chat/completions";
27pub const MOONSHOT_ORIGIN: &str = "https://api.moonshot.ai";
28pub const MOONSHOT_CHAT_PATH: &str = "/v1/chat/completions";
29
30pub const DEEPSEEK_ORIGIN: &str = "https://api.deepseek.com";
37pub const DEEPSEEK_CHAT_PATH: &str = "/chat/completions";
38
39pub const ANTHROPIC_ORIGIN: &str = "https://api.anthropic.com";
48pub const ANTHROPIC_CHAT_PATH: &str = "/v1/messages";
49pub const ANTHROPIC_API_KEY_HEADER: &str = "x-api-key";
51pub const ANTHROPIC_VERSION_HEADER: &str = "anthropic-version";
53pub const ANTHROPIC_VERSION: &str = "2023-06-01";
55
56pub const GEMINI_ORIGIN: &str = "https://generativelanguage.googleapis.com";
65pub const GEMINI_GENERATE_CONTENT_PATH: &str = "/v1beta/models/{model}:generateContent";
68pub const GEMINI_API_KEY_HEADER: &str = "x-goog-api-key";
70
71#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
72#[serde(rename_all = "snake_case")]
73pub enum PhaseKind {
74 OpenaiSubscription,
75 OllamaCloud,
76 OpenrouterApi,
77 OllamaLocal,
78 QwenSubscription,
79 QwenApi,
80 GrokSubscription,
81 GrokApi,
82 ZaiSubscription,
83 ZaiApi,
84 KimiSubscription,
85 KimiApi,
86 DeepseekApi,
87 ClaudeSubscription,
88 ClaudeApi,
89 GeminiSubscription,
90 GeminiApi,
91 DirectMoonshotKimiExtension,
92 XaiGrokExtension,
93}
94
95#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
98#[serde(transparent)]
99pub struct PhaseId(String);
100
101impl PhaseId {
102 pub const OPENAI_SUBSCRIPTION: &'static str = "openai_subscription";
103 pub const OLLAMA_CLOUD: &'static str = "ollama_cloud";
104 pub const OPENROUTER_API: &'static str = "openrouter_api";
105 pub const OLLAMA_LOCAL: &'static str = "ollama_local";
106 pub const QWEN_SUBSCRIPTION: &'static str = "qwen_subscription";
107 pub const QWEN_API: &'static str = "qwen_api";
108 pub const GROK_SUBSCRIPTION: &'static str = "grok_subscription";
109 pub const GROK_API: &'static str = "grok_api";
110 pub const ZAI_SUBSCRIPTION: &'static str = "zai_subscription";
111 pub const ZAI_API: &'static str = "zai_api";
112 pub const KIMI_SUBSCRIPTION: &'static str = "kimi_subscription";
113 pub const KIMI_API: &'static str = "kimi_api";
114 pub const DEEPSEEK_API: &'static str = "deepseek_api";
115 pub const CLAUDE_SUBSCRIPTION: &'static str = "claude_subscription";
116 pub const CLAUDE_API: &'static str = "claude_api";
117 pub const GEMINI_SUBSCRIPTION: &'static str = "gemini_subscription";
118 pub const GEMINI_API: &'static str = "gemini_api";
119
120 pub fn parse(value: impl Into<String>) -> Result<Self, RouteIdentityError> {
121 let value = value.into();
122 if value.is_empty()
123 || value.len() > 128
124 || !value
125 .bytes()
126 .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.'))
127 {
128 return Err(RouteIdentityError::InvalidPhaseId);
129 }
130 Ok(Self(value))
131 }
132
133 pub fn as_str(&self) -> &str {
134 &self.0
135 }
136}
137
138impl fmt::Display for PhaseId {
139 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
140 formatter.write_str(&self.0)
141 }
142}
143
144impl<'de> Deserialize<'de> for PhaseId {
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 Self::parse(String::deserialize(deserializer)?).map_err(serde::de::Error::custom)
150 }
151}
152
153impl PhaseKind {
154 pub const BUILTIN_ORDER: [Self; 4] = [
160 Self::OpenaiSubscription,
161 Self::OllamaCloud,
162 Self::OpenrouterApi,
163 Self::OllamaLocal,
164 ];
165
166 pub const fn is_builtin(self) -> bool {
167 matches!(
168 self,
169 Self::OpenaiSubscription
170 | Self::OllamaCloud
171 | Self::OpenrouterApi
172 | Self::OllamaLocal
173 | Self::QwenSubscription
174 | Self::QwenApi
175 | Self::GrokSubscription
176 | Self::GrokApi
177 | Self::ZaiSubscription
178 | Self::ZaiApi
179 | Self::KimiSubscription
180 | Self::KimiApi
181 | Self::DeepseekApi
182 | Self::ClaudeSubscription
183 | Self::ClaudeApi
184 | Self::GeminiSubscription
185 | Self::GeminiApi
186 )
187 }
188}
189
190#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
191#[serde(rename_all = "snake_case")]
192pub enum ProviderService {
193 Openai,
194 OllamaCloud,
195 Openrouter,
196 OllamaLocal,
197 Qwen,
198 Grok,
199 Zai,
200 MoonshotKimi,
201 Xai,
202 Deepseek,
203 Claude,
204 Gemini,
205}
206
207#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
208#[serde(rename_all = "snake_case")]
209pub enum TransportKind {
210 HarnessManaged,
211 OllamaSignedInRelay,
212 DirectHttps,
213 OllamaLocalDaemon,
214 DisabledExtension,
215}
216
217#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
218#[serde(rename_all = "snake_case")]
219pub enum CredentialSourceKind {
220 HarnessManaged,
221 OllamaDaemonSession,
222 SecretRef,
223 None,
224 Unconfigured,
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
228#[serde(rename_all = "snake_case")]
229pub enum CatalogSourceKind {
230 OpenaiHarnessCatalog,
231 OllamaCloudCatalog,
232 OpenrouterCatalog,
233 OllamaLocalInventory,
234 QwenCatalog,
235 GrokCatalog,
236 ZaiCatalog,
237 KimiCatalog,
238 DeepseekCatalog,
239 ClaudeCatalog,
240 GeminiCatalog,
241 ExtensionCatalog,
242}
243
244#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
245#[serde(rename_all = "snake_case")]
246pub enum BillingAuthorityClass {
247 OpenaiSubscription,
248 OllamaCloud,
249 OpenrouterMeteredApi,
250 LocalCompute,
251 QwenSubscription,
252 QwenMeteredApi,
253 GrokSubscription,
254 GrokMeteredApi,
255 ZaiSubscription,
256 ZaiMeteredApi,
257 KimiSubscription,
258 KimiMeteredApi,
259 DeepseekMeteredApi,
260 ClaudeSubscription,
261 ClaudeMeteredApi,
262 GeminiSubscription,
263 GeminiMeteredApi,
264 ExtensionProvider,
265}
266
267#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
268#[serde(rename_all = "snake_case")]
269pub enum ModelNamespace {
270 Openai,
271 OllamaCloud,
272 Openrouter,
273 OllamaLocal,
274 Qwen,
275 Grok,
276 Zai,
277 MoonshotKimi,
278 Xai,
279 Deepseek,
280 Claude,
281 Gemini,
282}
283
284#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
285#[serde(rename_all = "snake_case")]
286pub enum ExecutionLocation {
287 RemoteCloud,
288 LocalMachine,
289}
290
291#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
292#[serde(rename_all = "snake_case")]
293pub enum PhasePlacement {
294 Builtin,
295 DisabledUnplacedExtension,
296}
297
298#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
306#[serde(rename_all = "snake_case")]
307pub enum MultiAgentCapability {
308 Native,
309 NamespaceUnsupported,
310 Disabled,
311}
312
313impl MultiAgentCapability {
314 pub const fn serves_subagents_natively(self) -> bool {
316 matches!(self, Self::Native)
317 }
318}
319
320impl PhaseKind {
321 pub const fn multi_agent_capability(self) -> MultiAgentCapability {
326 match self {
327 Self::OpenaiSubscription => MultiAgentCapability::Native,
328 Self::OllamaCloud
329 | Self::OpenrouterApi
330 | Self::OllamaLocal
331 | Self::QwenSubscription
332 | Self::QwenApi
333 | Self::GrokSubscription
334 | Self::GrokApi
335 | Self::ZaiSubscription
336 | Self::ZaiApi
337 | Self::KimiSubscription
338 | Self::KimiApi
339 | Self::DeepseekApi
340 | Self::ClaudeSubscription
341 | Self::ClaudeApi
342 | Self::GeminiSubscription
343 | Self::GeminiApi
344 | Self::DirectMoonshotKimiExtension
345 | Self::XaiGrokExtension => MultiAgentCapability::NamespaceUnsupported,
346 }
347 }
348}
349
350#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
355#[serde(rename_all = "snake_case")]
356pub enum MultiAgentVersion {
357 V1,
358 V2,
359 Disabled,
360}
361
362impl MultiAgentVersion {
363 pub const fn as_str(self) -> &'static str {
364 match self {
365 Self::V1 => "v1",
366 Self::V2 => "v2",
367 Self::Disabled => "disabled",
368 }
369 }
370}
371
372#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
376#[serde(rename_all = "snake_case")]
377pub enum MultiAgentWireApi {
378 Responses,
379}
380
381#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
385#[serde(rename_all = "snake_case")]
386pub enum ObservedNamespaceCallBehavior {
387 ReturnsNamespaceField,
390 BareNameNoNamespace,
393 FlattenedNamespaceName,
395 Disabled,
397}
398
399#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
403#[serde(deny_unknown_fields)]
404pub struct MultiAgentCapabilityProjection {
405 pub namespace_tools: bool,
409 pub multi_agent_version: MultiAgentVersion,
410 pub wire_api: MultiAgentWireApi,
411 pub observed_namespace_calls: ObservedNamespaceCallBehavior,
412}
413
414#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
419#[serde(rename_all = "snake_case")]
420pub enum MultiAgentNamespace {
421 Collaboration,
422 Agents,
423}
424
425impl MultiAgentNamespace {
426 pub const fn as_str(self) -> &'static str {
427 match self {
428 Self::Collaboration => "collaboration",
429 Self::Agents => "agents",
430 }
431 }
432}
433
434impl PhaseKind {
435 pub const fn multi_agent_v2_projection(self) -> MultiAgentCapabilityProjection {
441 match self {
442 Self::OpenaiSubscription => MultiAgentCapabilityProjection {
443 namespace_tools: true,
444 multi_agent_version: MultiAgentVersion::V2,
445 wire_api: MultiAgentWireApi::Responses,
446 observed_namespace_calls: ObservedNamespaceCallBehavior::ReturnsNamespaceField,
447 },
448 Self::OllamaCloud
449 | Self::OpenrouterApi
450 | Self::OllamaLocal
451 | Self::QwenSubscription
452 | Self::QwenApi
453 | Self::GrokSubscription
454 | Self::GrokApi
455 | Self::ZaiSubscription
456 | Self::ZaiApi
457 | Self::KimiSubscription
458 | Self::KimiApi
459 | Self::DeepseekApi
460 | Self::ClaudeSubscription
461 | Self::ClaudeApi
462 | Self::GeminiSubscription
463 | Self::GeminiApi
464 | Self::DirectMoonshotKimiExtension
465 | Self::XaiGrokExtension => MultiAgentCapabilityProjection {
466 namespace_tools: false,
467 multi_agent_version: MultiAgentVersion::V2,
468 wire_api: MultiAgentWireApi::Responses,
469 observed_namespace_calls: ObservedNamespaceCallBehavior::BareNameNoNamespace,
470 },
471 }
472 }
473}
474
475#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
476#[serde(deny_unknown_fields)]
477pub struct EndpointIdentity {
478 pub origin: String,
479 pub path: String,
480}
481
482#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
483#[serde(deny_unknown_fields)]
484pub struct RouteIdentity {
485 pub phase: PhaseKind,
486 pub placement: PhasePlacement,
487 pub provider: ProviderService,
488 pub transport: TransportKind,
489 pub endpoint: EndpointIdentity,
490 pub credential_source: CredentialSourceKind,
491 pub credential_ref: Option<String>,
492 #[serde(default)]
497 pub credential_refs: Vec<String>,
498 pub catalog_source: CatalogSourceKind,
499 pub catalog_ref: String,
500 pub billing_authority: BillingAuthorityClass,
501 pub model_namespace: ModelNamespace,
502 pub model_id: String,
503 pub execution_location: ExecutionLocation,
504 pub account_ref: String,
505 pub capacity_domain_ref: String,
506 #[serde(default)]
507 pub local_execution_proof: bool,
508 #[serde(default)]
509 pub approved_local_inventory: Vec<String>,
510 #[serde(default)]
514 pub reasoning_modes: Vec<String>,
515}
516
517#[derive(Clone, Copy, Debug, PartialEq, Eq, Error)]
518pub enum RouteIdentityError {
519 #[error("phase identity is invalid")]
520 InvalidPhaseId,
521 #[error("route identity is ambiguous or internally inconsistent")]
522 AmbiguousIdentity,
523 #[error("route endpoint does not match the frozen transport contract")]
524 InvalidEndpoint,
525 #[error("route credential source does not match its transport")]
526 InvalidCredentialSource,
527 #[error("local Ollama route lacks local execution and inventory proof")]
528 MissingLocalProof,
529 #[error("route reasoning mode claim is invalid")]
530 InvalidReasoningModes,
531 #[error("disabled extension cannot be placed or enabled")]
532 ExtensionMustRemainUnplaced,
533}
534
535impl RouteIdentity {
536 pub fn multi_agent_capability(&self) -> MultiAgentCapability {
539 if self.placement == PhasePlacement::DisabledUnplacedExtension {
540 return MultiAgentCapability::Disabled;
541 }
542 self.phase.multi_agent_capability()
543 }
544
545 pub fn multi_agent_v2_projection(&self) -> MultiAgentCapabilityProjection {
548 if self.placement == PhasePlacement::DisabledUnplacedExtension {
549 return MultiAgentCapabilityProjection {
550 namespace_tools: false,
551 multi_agent_version: MultiAgentVersion::Disabled,
552 wire_api: MultiAgentWireApi::Responses,
553 observed_namespace_calls: ObservedNamespaceCallBehavior::Disabled,
554 };
555 }
556 self.phase.multi_agent_v2_projection()
557 }
558
559 pub fn mav2_namespace_choice(&self) -> MultiAgentNamespace {
564 match self.phase {
565 PhaseKind::OpenaiSubscription => MultiAgentNamespace::Collaboration,
566 PhaseKind::OllamaCloud
567 | PhaseKind::OpenrouterApi
568 | PhaseKind::OllamaLocal
569 | PhaseKind::QwenSubscription
570 | PhaseKind::QwenApi
571 | PhaseKind::GrokSubscription
572 | PhaseKind::GrokApi
573 | PhaseKind::ZaiSubscription
574 | PhaseKind::ZaiApi
575 | PhaseKind::KimiSubscription
576 | PhaseKind::KimiApi
577 | PhaseKind::DeepseekApi
578 | PhaseKind::ClaudeSubscription
579 | PhaseKind::ClaudeApi
580 | PhaseKind::GeminiSubscription
581 | PhaseKind::GeminiApi
582 | PhaseKind::DirectMoonshotKimiExtension
583 | PhaseKind::XaiGrokExtension => MultiAgentNamespace::Agents,
584 }
585 }
586
587 pub fn multi_agent_version_served(&self) -> MultiAgentVersion {
589 self.multi_agent_v2_projection().multi_agent_version
590 }
591
592 pub fn validate(&self) -> Result<(), RouteIdentityError> {
593 if !valid_ref(&self.account_ref)
594 || !valid_ref(&self.capacity_domain_ref)
595 || !valid_ref(&self.catalog_ref)
596 || !valid_model_id(&self.model_id)
597 {
598 return Err(RouteIdentityError::AmbiguousIdentity);
599 }
600 if self.reasoning_modes.len() > 8
601 || self.reasoning_modes.iter().any(|mode| !valid_ref(mode))
602 || self.reasoning_modes.iter().collect::<HashSet<_>>().len()
603 != self.reasoning_modes.len()
604 {
605 return Err(RouteIdentityError::InvalidReasoningModes);
606 }
607 self.validate_credential_pool()?;
608 if self.phase.is_builtin() != (self.placement == PhasePlacement::Builtin) {
609 return Err(RouteIdentityError::ExtensionMustRemainUnplaced);
610 }
611 if !self.phase.is_builtin() {
612 return self.validate_extension();
613 }
614
615 match self.phase {
616 PhaseKind::OpenaiSubscription => self.validate_openai_subscription(),
617 PhaseKind::OllamaCloud => self.validate_ollama_cloud(),
618 PhaseKind::OpenrouterApi => self.validate_openrouter(),
619 PhaseKind::OllamaLocal => self.validate_ollama_local(),
620 PhaseKind::QwenSubscription => self.validate_qwen_subscription(),
621 PhaseKind::QwenApi => self.validate_qwen_api(),
622 PhaseKind::GrokSubscription => self.validate_grok_subscription(),
623 PhaseKind::GrokApi => self.validate_grok_api(),
624 PhaseKind::ZaiSubscription => self.validate_zai_subscription(),
625 PhaseKind::ZaiApi => self.validate_zai_api(),
626 PhaseKind::KimiSubscription => self.validate_kimi_subscription(),
627 PhaseKind::KimiApi => self.validate_kimi_api(),
628 PhaseKind::DeepseekApi => self.validate_deepseek_api(),
629 PhaseKind::ClaudeSubscription => self.validate_claude_subscription(),
630 PhaseKind::ClaudeApi => self.validate_claude_api(),
631 PhaseKind::GeminiSubscription => self.validate_gemini_subscription(),
632 PhaseKind::GeminiApi => self.validate_gemini_api(),
633 PhaseKind::DirectMoonshotKimiExtension | PhaseKind::XaiGrokExtension => {
634 Err(RouteIdentityError::ExtensionMustRemainUnplaced)
635 }
636 }
637 }
638
639 fn validate_credential_pool(&self) -> Result<(), RouteIdentityError> {
646 if self.credential_refs.is_empty() {
647 return Ok(());
648 }
649 if self.credential_refs.iter().collect::<HashSet<_>>().len() != self.credential_refs.len() {
650 return Err(RouteIdentityError::AmbiguousIdentity);
651 }
652 if self
653 .credential_refs
654 .iter()
655 .any(|reference| !valid_secret_ref(reference))
656 {
657 return Err(RouteIdentityError::InvalidCredentialSource);
658 }
659 if self.credential_ref.as_deref() != self.credential_refs.first().map(String::as_str) {
660 return Err(RouteIdentityError::AmbiguousIdentity);
661 }
662 Ok(())
663 }
664
665 fn validate_openai_subscription(&self) -> Result<(), RouteIdentityError> {
666 if self.provider != ProviderService::Openai
667 || self.transport != TransportKind::HarnessManaged
668 || self.credential_source != CredentialSourceKind::HarnessManaged
669 || self.credential_ref.is_some()
670 || self.catalog_source != CatalogSourceKind::OpenaiHarnessCatalog
671 || self.billing_authority != BillingAuthorityClass::OpenaiSubscription
672 || self.model_namespace != ModelNamespace::Openai
673 || self.execution_location != ExecutionLocation::RemoteCloud
674 || self.endpoint.origin != "harness://codex-app-server"
675 || self.endpoint.path != "/responses"
676 {
677 return Err(RouteIdentityError::AmbiguousIdentity);
678 }
679 Ok(())
680 }
681
682 fn validate_ollama_cloud(&self) -> Result<(), RouteIdentityError> {
683 if self.provider != ProviderService::OllamaCloud
684 || self.catalog_source != CatalogSourceKind::OllamaCloudCatalog
685 || self.billing_authority != BillingAuthorityClass::OllamaCloud
686 || self.model_namespace != ModelNamespace::OllamaCloud
687 || self.execution_location != ExecutionLocation::RemoteCloud
688 {
689 return Err(RouteIdentityError::AmbiguousIdentity);
690 }
691 match self.transport {
692 TransportKind::OllamaSignedInRelay => {
693 if self.endpoint.origin != OLLAMA_RELAY_ORIGIN
694 || self.endpoint.path != OLLAMA_CHAT_PATH
695 {
696 return Err(RouteIdentityError::InvalidEndpoint);
697 }
698 if self.credential_source != CredentialSourceKind::OllamaDaemonSession
699 || self.credential_ref.is_some()
700 || !valid_ollama_cloud_wire_model(
701 &self.model_id,
702 TransportKind::OllamaSignedInRelay,
703 )
704 {
705 return Err(RouteIdentityError::InvalidCredentialSource);
706 }
707 }
708 TransportKind::DirectHttps => {
709 if self.endpoint.origin != OLLAMA_CLOUD_ORIGIN
710 || self.endpoint.path != OLLAMA_CHAT_PATH
711 {
712 return Err(RouteIdentityError::InvalidEndpoint);
713 }
714 if self.credential_source != CredentialSourceKind::SecretRef
715 || self
716 .credential_ref
717 .as_deref()
718 .is_none_or(|value| !valid_secret_ref(value))
719 || !valid_ollama_cloud_wire_model(&self.model_id, TransportKind::DirectHttps)
720 {
721 return Err(RouteIdentityError::InvalidCredentialSource);
722 }
723 }
724 _ => return Err(RouteIdentityError::AmbiguousIdentity),
725 }
726 Ok(())
727 }
728
729 fn validate_openrouter(&self) -> Result<(), RouteIdentityError> {
730 if self.provider != ProviderService::Openrouter
731 || self.transport != TransportKind::DirectHttps
732 || self.endpoint.origin != OPENROUTER_ORIGIN
733 || self.endpoint.path != OPENROUTER_CHAT_PATH
734 || self.credential_source != CredentialSourceKind::SecretRef
735 || self
736 .credential_ref
737 .as_deref()
738 .is_none_or(|value| !valid_secret_ref(value))
739 || self.catalog_source != CatalogSourceKind::OpenrouterCatalog
740 || self.billing_authority != BillingAuthorityClass::OpenrouterMeteredApi
741 || self.model_namespace != ModelNamespace::Openrouter
742 || self.execution_location != ExecutionLocation::RemoteCloud
743 {
744 return Err(RouteIdentityError::AmbiguousIdentity);
745 }
746 Ok(())
747 }
748
749 fn validate_ollama_local(&self) -> Result<(), RouteIdentityError> {
750 if self.provider != ProviderService::OllamaLocal
751 || self.transport != TransportKind::OllamaLocalDaemon
752 || self.endpoint.origin != OLLAMA_RELAY_ORIGIN
753 || self.endpoint.path != OLLAMA_CHAT_PATH
754 || self.credential_source != CredentialSourceKind::None
755 || self.credential_ref.is_some()
756 || self.catalog_source != CatalogSourceKind::OllamaLocalInventory
757 || self.billing_authority != BillingAuthorityClass::LocalCompute
758 || self.model_namespace != ModelNamespace::OllamaLocal
759 || self.execution_location != ExecutionLocation::LocalMachine
760 {
761 return Err(RouteIdentityError::AmbiguousIdentity);
762 }
763 if !self.local_execution_proof
764 || has_ollama_cloud_wire_suffix(&self.model_id)
765 || !self
766 .approved_local_inventory
767 .iter()
768 .any(|model| model == &self.model_id && !has_ollama_cloud_wire_suffix(model))
769 {
770 return Err(RouteIdentityError::MissingLocalProof);
771 }
772 Ok(())
773 }
774
775 fn validate_follow_on_route(
780 &self,
781 provider: ProviderService,
782 origin: &str,
783 path: &str,
784 catalog_source: CatalogSourceKind,
785 billing_authority: BillingAuthorityClass,
786 namespace: ModelNamespace,
787 ) -> Result<(), RouteIdentityError> {
788 self.validate_follow_on_route_any(
789 provider,
790 &[origin],
791 path,
792 catalog_source,
793 billing_authority,
794 namespace,
795 )
796 }
797
798 fn validate_follow_on_route_any(
805 &self,
806 provider: ProviderService,
807 origins: &[&str],
808 path: &str,
809 catalog_source: CatalogSourceKind,
810 billing_authority: BillingAuthorityClass,
811 namespace: ModelNamespace,
812 ) -> Result<(), RouteIdentityError> {
813 if self.provider != provider
814 || self.transport != TransportKind::DirectHttps
815 || !origins.contains(&self.endpoint.origin.as_str())
816 || self.endpoint.path != path
817 || self.credential_source != CredentialSourceKind::SecretRef
818 || self
819 .credential_ref
820 .as_deref()
821 .is_none_or(|value| !valid_secret_ref(value))
822 || self.catalog_source != catalog_source
823 || self.billing_authority != billing_authority
824 || self.model_namespace != namespace
825 || self.execution_location != ExecutionLocation::RemoteCloud
826 {
827 return Err(RouteIdentityError::AmbiguousIdentity);
828 }
829 Ok(())
830 }
831
832 fn validate_qwen_subscription(&self) -> Result<(), RouteIdentityError> {
833 self.validate_follow_on_route_any(
834 ProviderService::Qwen,
835 &[DASHSCOPE_ORIGIN, DASHSCOPE_TOKEN_PLAN_ORIGIN],
836 DASHSCOPE_CHAT_PATH,
837 CatalogSourceKind::QwenCatalog,
838 BillingAuthorityClass::QwenSubscription,
839 ModelNamespace::Qwen,
840 )
841 }
842
843 fn validate_qwen_api(&self) -> Result<(), RouteIdentityError> {
844 self.validate_follow_on_route_any(
845 ProviderService::Qwen,
846 &[DASHSCOPE_ORIGIN, DASHSCOPE_TOKEN_PLAN_ORIGIN],
847 DASHSCOPE_CHAT_PATH,
848 CatalogSourceKind::QwenCatalog,
849 BillingAuthorityClass::QwenMeteredApi,
850 ModelNamespace::Qwen,
851 )
852 }
853
854 fn validate_grok_subscription(&self) -> Result<(), RouteIdentityError> {
855 self.validate_follow_on_route(
856 ProviderService::Grok,
857 XAI_ORIGIN,
858 XAI_CHAT_PATH,
859 CatalogSourceKind::GrokCatalog,
860 BillingAuthorityClass::GrokSubscription,
861 ModelNamespace::Grok,
862 )
863 }
864
865 fn validate_grok_api(&self) -> Result<(), RouteIdentityError> {
866 self.validate_follow_on_route(
867 ProviderService::Grok,
868 XAI_ORIGIN,
869 XAI_CHAT_PATH,
870 CatalogSourceKind::GrokCatalog,
871 BillingAuthorityClass::GrokMeteredApi,
872 ModelNamespace::Grok,
873 )
874 }
875
876 fn validate_zai_subscription(&self) -> Result<(), RouteIdentityError> {
877 self.validate_follow_on_route(
878 ProviderService::Zai,
879 ZAI_ORIGIN,
880 ZAI_CHAT_PATH,
881 CatalogSourceKind::ZaiCatalog,
882 BillingAuthorityClass::ZaiSubscription,
883 ModelNamespace::Zai,
884 )
885 }
886
887 fn validate_zai_api(&self) -> Result<(), RouteIdentityError> {
888 self.validate_follow_on_route(
889 ProviderService::Zai,
890 ZAI_ORIGIN,
891 ZAI_CHAT_PATH,
892 CatalogSourceKind::ZaiCatalog,
893 BillingAuthorityClass::ZaiMeteredApi,
894 ModelNamespace::Zai,
895 )
896 }
897
898 fn validate_kimi_subscription(&self) -> Result<(), RouteIdentityError> {
899 self.validate_follow_on_route(
900 ProviderService::MoonshotKimi,
901 MOONSHOT_ORIGIN,
902 MOONSHOT_CHAT_PATH,
903 CatalogSourceKind::KimiCatalog,
904 BillingAuthorityClass::KimiSubscription,
905 ModelNamespace::MoonshotKimi,
906 )
907 }
908
909 fn validate_kimi_api(&self) -> Result<(), RouteIdentityError> {
910 self.validate_follow_on_route(
911 ProviderService::MoonshotKimi,
912 MOONSHOT_ORIGIN,
913 MOONSHOT_CHAT_PATH,
914 CatalogSourceKind::KimiCatalog,
915 BillingAuthorityClass::KimiMeteredApi,
916 ModelNamespace::MoonshotKimi,
917 )
918 }
919
920 fn validate_deepseek_api(&self) -> Result<(), RouteIdentityError> {
926 self.validate_follow_on_route(
927 ProviderService::Deepseek,
928 DEEPSEEK_ORIGIN,
929 DEEPSEEK_CHAT_PATH,
930 CatalogSourceKind::DeepseekCatalog,
931 BillingAuthorityClass::DeepseekMeteredApi,
932 ModelNamespace::Deepseek,
933 )
934 }
935
936 fn validate_claude_subscription(&self) -> Result<(), RouteIdentityError> {
944 self.validate_follow_on_route(
945 ProviderService::Claude,
946 ANTHROPIC_ORIGIN,
947 ANTHROPIC_CHAT_PATH,
948 CatalogSourceKind::ClaudeCatalog,
949 BillingAuthorityClass::ClaudeSubscription,
950 ModelNamespace::Claude,
951 )
952 }
953
954 fn validate_claude_api(&self) -> Result<(), RouteIdentityError> {
955 self.validate_follow_on_route(
956 ProviderService::Claude,
957 ANTHROPIC_ORIGIN,
958 ANTHROPIC_CHAT_PATH,
959 CatalogSourceKind::ClaudeCatalog,
960 BillingAuthorityClass::ClaudeMeteredApi,
961 ModelNamespace::Claude,
962 )
963 }
964
965 fn validate_gemini_subscription(&self) -> Result<(), RouteIdentityError> {
974 self.validate_gemini_route(BillingAuthorityClass::GeminiSubscription)
975 }
976
977 fn validate_gemini_api(&self) -> Result<(), RouteIdentityError> {
978 self.validate_gemini_route(BillingAuthorityClass::GeminiMeteredApi)
979 }
980
981 fn validate_gemini_route(
982 &self,
983 billing_authority: BillingAuthorityClass,
984 ) -> Result<(), RouteIdentityError> {
985 if self.provider != ProviderService::Gemini
986 || self.transport != TransportKind::DirectHttps
987 || self.endpoint.origin != GEMINI_ORIGIN
988 || self.endpoint.path != GEMINI_GENERATE_CONTENT_PATH
989 || self.credential_source != CredentialSourceKind::SecretRef
990 || self
991 .credential_ref
992 .as_deref()
993 .is_none_or(|value| !valid_secret_ref(value))
994 || self.catalog_source != CatalogSourceKind::GeminiCatalog
995 || self.billing_authority != billing_authority
996 || self.model_namespace != ModelNamespace::Gemini
997 || self.execution_location != ExecutionLocation::RemoteCloud
998 {
999 return Err(RouteIdentityError::AmbiguousIdentity);
1000 }
1001 Ok(())
1002 }
1003
1004 fn validate_extension(&self) -> Result<(), RouteIdentityError> {
1005 let expected = match self.phase {
1006 PhaseKind::DirectMoonshotKimiExtension => {
1007 (ProviderService::MoonshotKimi, ModelNamespace::MoonshotKimi)
1008 }
1009 PhaseKind::XaiGrokExtension => (ProviderService::Xai, ModelNamespace::Xai),
1010 _ => return Err(RouteIdentityError::ExtensionMustRemainUnplaced),
1011 };
1012 if self.placement != PhasePlacement::DisabledUnplacedExtension
1013 || self.provider != expected.0
1014 || self.model_namespace != expected.1
1015 || self.transport != TransportKind::DisabledExtension
1016 || self.credential_source != CredentialSourceKind::Unconfigured
1017 || self.credential_ref.is_some()
1018 || self.catalog_source != CatalogSourceKind::ExtensionCatalog
1019 || self.billing_authority != BillingAuthorityClass::ExtensionProvider
1020 {
1021 return Err(RouteIdentityError::ExtensionMustRemainUnplaced);
1022 }
1023 Ok(())
1024 }
1025}
1026
1027pub fn ollama_cloud_wire_model(
1032 provider_neutral_model: &str,
1033 transport: TransportKind,
1034) -> Result<String, RouteIdentityError> {
1035 if !valid_model_id(provider_neutral_model)
1036 || has_ollama_cloud_wire_suffix(provider_neutral_model)
1037 {
1038 return Err(RouteIdentityError::AmbiguousIdentity);
1039 }
1040 match transport {
1041 TransportKind::OllamaSignedInRelay => Ok(format!("{provider_neutral_model}:cloud")),
1042 TransportKind::DirectHttps => Ok(provider_neutral_model.to_owned()),
1043 _ => Err(RouteIdentityError::AmbiguousIdentity),
1044 }
1045}
1046
1047pub fn ollama_cloud_provider_neutral_model(
1053 wire_model: &str,
1054 transport: TransportKind,
1055) -> Result<String, RouteIdentityError> {
1056 if !valid_model_id(wire_model) {
1057 return Err(RouteIdentityError::AmbiguousIdentity);
1058 }
1059 match transport {
1060 TransportKind::OllamaSignedInRelay => cloud_base_model_id(wire_model)
1061 .map(str::to_owned)
1062 .ok_or(RouteIdentityError::AmbiguousIdentity),
1063 TransportKind::DirectHttps if !has_ollama_cloud_wire_suffix(wire_model) => {
1064 Ok(wire_model.to_owned())
1065 }
1066 _ => Err(RouteIdentityError::AmbiguousIdentity),
1067 }
1068}
1069
1070fn valid_ollama_cloud_wire_model(model_id: &str, transport: TransportKind) -> bool {
1071 ollama_cloud_provider_neutral_model(model_id, transport).is_ok()
1072}
1073
1074fn cloud_base_model_id(value: &str) -> Option<&str> {
1075 let base = value
1076 .strip_suffix(":cloud")
1077 .or_else(|| value.strip_suffix("-cloud"))?;
1078 (!base.is_empty() && valid_model_id(base) && !has_ollama_cloud_wire_suffix(base))
1079 .then_some(base)
1080}
1081
1082fn has_ollama_cloud_wire_suffix(value: &str) -> bool {
1083 value.ends_with(":cloud") || value.ends_with("-cloud")
1084}
1085
1086fn valid_ref(value: &str) -> bool {
1087 !value.is_empty()
1088 && value.len() <= 256
1089 && value.bytes().all(|byte| {
1090 byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b':' | b'/')
1091 })
1092}
1093
1094fn valid_model_id(value: &str) -> bool {
1095 valid_ref(value) && !value.contains("..")
1096}
1097
1098fn valid_secret_ref(value: &str) -> bool {
1099 if !valid_ref(value) {
1100 return false;
1101 }
1102 if let Some(name) = value.strip_prefix("env:") {
1103 return valid_environment_name(name);
1106 }
1107 [
1108 "local-file-v1:",
1109 "command:",
1110 "keychain:",
1111 "secret-service:",
1112 "credential-manager:",
1113 ]
1114 .iter()
1115 .any(|prefix| value.starts_with(prefix))
1116}
1117
1118fn valid_environment_name(value: &str) -> bool {
1122 !value.is_empty()
1123 && value.len() <= 256
1124 && value
1125 .bytes()
1126 .all(|byte| byte.is_ascii_alphanumeric() || byte == b'_')
1127}
1128
1129#[cfg(test)]
1130mod tests {
1131 use super::*;
1132
1133 fn cloud_identity(transport: TransportKind, model_id: &str) -> RouteIdentity {
1134 let direct = transport == TransportKind::DirectHttps;
1135 RouteIdentity {
1136 phase: PhaseKind::OllamaCloud,
1137 placement: PhasePlacement::Builtin,
1138 provider: ProviderService::OllamaCloud,
1139 transport,
1140 endpoint: EndpointIdentity {
1141 origin: if direct {
1142 OLLAMA_CLOUD_ORIGIN
1143 } else {
1144 OLLAMA_RELAY_ORIGIN
1145 }
1146 .to_owned(),
1147 path: OLLAMA_CHAT_PATH.to_owned(),
1148 },
1149 credential_source: if direct {
1150 CredentialSourceKind::SecretRef
1151 } else {
1152 CredentialSourceKind::OllamaDaemonSession
1153 },
1154 credential_ref: direct.then(|| "keychain:ollama-cloud-device".to_owned()),
1155 credential_refs: Vec::new(),
1156 catalog_source: CatalogSourceKind::OllamaCloudCatalog,
1157 catalog_ref: "catalog:v2:ollama-cloud".to_owned(),
1158 billing_authority: BillingAuthorityClass::OllamaCloud,
1159 model_namespace: ModelNamespace::OllamaCloud,
1160 model_id: model_id.to_owned(),
1161 execution_location: ExecutionLocation::RemoteCloud,
1162 account_ref: "ollama-cloud-held".to_owned(),
1163 capacity_domain_ref: "capacity:ollama-cloud-held".to_owned(),
1164 local_execution_proof: false,
1165 approved_local_inventory: Vec::new(),
1166 reasoning_modes: vec!["reasoning".to_owned()],
1167 }
1168 }
1169
1170 #[test]
1171 fn ollama_cloud_wire_model_is_transport_specific_and_single_suffix() {
1172 assert_eq!(
1173 ollama_cloud_wire_model(OLLAMA_GLM_5_2_MODEL, TransportKind::OllamaSignedInRelay),
1174 Ok("glm-5.2:cloud".to_owned())
1175 );
1176 assert_eq!(
1177 ollama_cloud_wire_model(OLLAMA_GLM_5_2_MODEL, TransportKind::DirectHttps),
1178 Ok("glm-5.2".to_owned())
1179 );
1180 assert!(
1181 ollama_cloud_wire_model("glm-5.2:cloud", TransportKind::OllamaSignedInRelay).is_err()
1182 );
1183 assert!(
1184 ollama_cloud_wire_model("qwen3-coder:480b-cloud", TransportKind::OllamaSignedInRelay)
1185 .is_err()
1186 );
1187 assert!(
1188 ollama_cloud_wire_model(OLLAMA_GLM_5_2_MODEL, TransportKind::OllamaLocalDaemon)
1189 .is_err()
1190 );
1191
1192 assert!(
1193 cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2:cloud")
1194 .validate()
1195 .is_ok()
1196 );
1197 assert!(
1198 cloud_identity(TransportKind::OllamaSignedInRelay, "qwen3-coder:480b-cloud")
1199 .validate()
1200 .is_ok()
1201 );
1202 assert!(
1203 cloud_identity(TransportKind::OllamaSignedInRelay, "gpt-oss:120b-cloud")
1204 .validate()
1205 .is_ok()
1206 );
1207 assert!(
1208 cloud_identity(TransportKind::OllamaSignedInRelay, "kimi-k2.6:cloud")
1209 .validate()
1210 .is_ok()
1211 );
1212 assert!(
1213 cloud_identity(TransportKind::DirectHttps, "glm-5.2")
1214 .validate()
1215 .is_ok()
1216 );
1217 assert!(
1218 cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2:cloud:cloud")
1219 .validate()
1220 .is_err()
1221 );
1222 for invalid in [
1223 "model-cloud-cloud",
1224 "model:cloud-cloud",
1225 "model-cloud:cloud",
1226 "model:cloud:cloud",
1227 ] {
1228 assert!(
1229 cloud_identity(TransportKind::OllamaSignedInRelay, invalid)
1230 .validate()
1231 .is_err(),
1232 "accepted non-canonical double suffix {invalid}"
1233 );
1234 }
1235 assert!(
1236 cloud_identity(TransportKind::DirectHttps, "glm-5.2:cloud")
1237 .validate()
1238 .is_err()
1239 );
1240 assert!(
1241 cloud_identity(TransportKind::DirectHttps, "qwen3-coder:480b-cloud")
1242 .validate()
1243 .is_err()
1244 );
1245 assert_eq!(
1246 ollama_cloud_provider_neutral_model(
1247 "qwen3-coder:480b-cloud",
1248 TransportKind::OllamaSignedInRelay
1249 ),
1250 Ok("qwen3-coder:480b".to_owned())
1251 );
1252 assert_eq!(
1253 ollama_cloud_provider_neutral_model("glm-5.2", TransportKind::DirectHttps),
1254 Ok("glm-5.2".to_owned())
1255 );
1256 }
1257
1258 #[test]
1259 fn multi_agent_capability_projection_matches_phase_kind() {
1260 assert_eq!(
1261 PhaseKind::OpenaiSubscription.multi_agent_capability(),
1262 MultiAgentCapability::Native
1263 );
1264 assert!(
1265 PhaseKind::OpenaiSubscription
1266 .multi_agent_capability()
1267 .serves_subagents_natively()
1268 );
1269 for phase in [
1270 PhaseKind::OllamaCloud,
1271 PhaseKind::OpenrouterApi,
1272 PhaseKind::OllamaLocal,
1273 PhaseKind::DirectMoonshotKimiExtension,
1274 PhaseKind::XaiGrokExtension,
1275 ] {
1276 assert_eq!(
1277 phase.multi_agent_capability(),
1278 MultiAgentCapability::NamespaceUnsupported
1279 );
1280 assert!(!phase.multi_agent_capability().serves_subagents_natively());
1281 }
1282 }
1283
1284 #[test]
1285 fn disabled_extension_route_is_never_native() {
1286 let mut identity = cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2");
1287 identity.placement = PhasePlacement::DisabledUnplacedExtension;
1288 assert_eq!(
1289 identity.multi_agent_capability(),
1290 MultiAgentCapability::Disabled
1291 );
1292 assert!(
1293 !identity
1294 .multi_agent_capability()
1295 .serves_subagents_natively()
1296 );
1297 }
1298
1299 #[test]
1300 fn mav2_projection_is_per_route_and_matches_phase_kind() {
1301 let openai = RouteIdentity {
1302 phase: PhaseKind::OpenaiSubscription,
1303 placement: PhasePlacement::Builtin,
1304 provider: ProviderService::Openai,
1305 transport: TransportKind::HarnessManaged,
1306 endpoint: EndpointIdentity {
1307 origin: "harness://codex-app-server".to_owned(),
1308 path: "/responses".to_owned(),
1309 },
1310 credential_source: CredentialSourceKind::HarnessManaged,
1311 credential_ref: None,
1312 credential_refs: Vec::new(),
1313 catalog_source: CatalogSourceKind::OpenaiHarnessCatalog,
1314 catalog_ref: "catalog:v2:openai-harness".to_owned(),
1315 billing_authority: BillingAuthorityClass::OpenaiSubscription,
1316 model_namespace: ModelNamespace::Openai,
1317 model_id: "gpt-5.6-sol".to_owned(),
1318 execution_location: ExecutionLocation::RemoteCloud,
1319 account_ref: "openai-subscription-held".to_owned(),
1320 capacity_domain_ref: "capacity:openai-subscription-held".to_owned(),
1321 local_execution_proof: false,
1322 approved_local_inventory: Vec::new(),
1323 reasoning_modes: vec!["reasoning".to_owned()],
1324 };
1325 assert!(openai.validate().is_ok());
1326 let openai_projection = openai.multi_agent_v2_projection();
1327 assert_eq!(
1328 openai_projection,
1329 MultiAgentCapabilityProjection {
1330 namespace_tools: true,
1331 multi_agent_version: MultiAgentVersion::V2,
1332 wire_api: MultiAgentWireApi::Responses,
1333 observed_namespace_calls: ObservedNamespaceCallBehavior::ReturnsNamespaceField,
1334 }
1335 );
1336 assert_eq!(
1337 openai.mav2_namespace_choice(),
1338 MultiAgentNamespace::Collaboration
1339 );
1340 assert_eq!(openai.mav2_namespace_choice().as_str(), "collaboration");
1341
1342 let cloud = cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2:cloud");
1343 let cloud_projection = cloud.multi_agent_v2_projection();
1344 assert_eq!(
1345 cloud_projection,
1346 MultiAgentCapabilityProjection {
1347 namespace_tools: false,
1348 multi_agent_version: MultiAgentVersion::V2,
1349 wire_api: MultiAgentWireApi::Responses,
1350 observed_namespace_calls: ObservedNamespaceCallBehavior::BareNameNoNamespace,
1351 }
1352 );
1353 assert_eq!(cloud.mav2_namespace_choice(), MultiAgentNamespace::Agents);
1354 assert_eq!(cloud.mav2_namespace_choice().as_str(), "agents");
1355 }
1356
1357 #[test]
1358 fn mav2_projection_for_disabled_extension_is_never_namespace_capable() {
1359 let mut identity = cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2");
1360 identity.placement = PhasePlacement::DisabledUnplacedExtension;
1361 assert_eq!(
1362 identity.multi_agent_v2_projection(),
1363 MultiAgentCapabilityProjection {
1364 namespace_tools: false,
1365 multi_agent_version: MultiAgentVersion::Disabled,
1366 wire_api: MultiAgentWireApi::Responses,
1367 observed_namespace_calls: ObservedNamespaceCallBehavior::Disabled,
1368 }
1369 );
1370 assert_eq!(
1371 identity.multi_agent_version_served(),
1372 MultiAgentVersion::Disabled
1373 );
1374 }
1375
1376 #[test]
1377 fn credential_pool_invariant_rejects_invalid_entries() {
1378 let mut valid = cloud_identity(TransportKind::DirectHttps, "glm-5.2");
1380 valid.credential_refs = vec![
1381 "keychain:ollama-cloud-device".to_owned(),
1382 "keychain:ollama-cloud-device-2".to_owned(),
1383 ];
1384 assert!(valid.validate().is_ok());
1385
1386 let mut duplicate = cloud_identity(TransportKind::DirectHttps, "glm-5.2");
1388 duplicate.credential_refs = vec![
1389 "keychain:ollama-cloud-device".to_owned(),
1390 "keychain:ollama-cloud-device".to_owned(),
1391 ];
1392 assert!(duplicate.validate().is_err());
1393
1394 let mut invalid = cloud_identity(TransportKind::DirectHttps, "glm-5.2");
1396 invalid.credential_refs = vec!["not-a-secret-ref".to_owned()];
1397 assert!(invalid.validate().is_err());
1398
1399 let mut fallback = cloud_identity(TransportKind::DirectHttps, "glm-5.2");
1401 fallback.credential_refs = vec![
1402 "keychain:ollama-cloud-device".to_owned(),
1403 "keychain:ollama-cloud-device-2".to_owned(),
1404 ];
1405 fallback.credential_ref = Some("keychain:ollama-cloud-device-2".to_owned());
1406 assert!(fallback.validate().is_err());
1407
1408 let mut relay = cloud_identity(TransportKind::OllamaSignedInRelay, "glm-5.2:cloud");
1411 relay.credential_refs = vec!["keychain:ollama-cloud-device".to_owned()];
1412 assert!(relay.validate().is_err());
1413 }
1414
1415 fn follow_on_identity(
1416 phase: PhaseKind,
1417 provider: ProviderService,
1418 origin: &str,
1419 path: &str,
1420 catalog_source: CatalogSourceKind,
1421 billing_authority: BillingAuthorityClass,
1422 namespace: ModelNamespace,
1423 ) -> RouteIdentity {
1424 RouteIdentity {
1425 phase,
1426 placement: PhasePlacement::Builtin,
1427 provider,
1428 transport: TransportKind::DirectHttps,
1429 endpoint: EndpointIdentity {
1430 origin: origin.to_owned(),
1431 path: path.to_owned(),
1432 },
1433 credential_source: CredentialSourceKind::SecretRef,
1434 credential_ref: Some("env:STEADYMUX_FOLLOW_ON_KEY".to_owned()),
1435 credential_refs: vec!["env:STEADYMUX_FOLLOW_ON_KEY".to_owned()],
1436 catalog_source,
1437 catalog_ref: "catalog:v2:follow-on".to_owned(),
1438 billing_authority,
1439 model_namespace: namespace,
1440 model_id: "follow-on/fixture".to_owned(),
1441 execution_location: ExecutionLocation::RemoteCloud,
1442 account_ref: "account:follow-on".to_owned(),
1443 capacity_domain_ref: "capacity:follow-on".to_owned(),
1444 local_execution_proof: false,
1445 approved_local_inventory: Vec::new(),
1446 reasoning_modes: Vec::new(),
1447 }
1448 }
1449
1450 #[test]
1451 fn follow_on_provider_phases_validate_as_first_class_routes() {
1452 let cases = [
1453 (
1454 PhaseKind::QwenSubscription,
1455 ProviderService::Qwen,
1456 DASHSCOPE_ORIGIN,
1457 DASHSCOPE_CHAT_PATH,
1458 CatalogSourceKind::QwenCatalog,
1459 BillingAuthorityClass::QwenSubscription,
1460 ModelNamespace::Qwen,
1461 ),
1462 (
1463 PhaseKind::QwenApi,
1464 ProviderService::Qwen,
1465 DASHSCOPE_ORIGIN,
1466 DASHSCOPE_CHAT_PATH,
1467 CatalogSourceKind::QwenCatalog,
1468 BillingAuthorityClass::QwenMeteredApi,
1469 ModelNamespace::Qwen,
1470 ),
1471 (
1472 PhaseKind::QwenApi,
1473 ProviderService::Qwen,
1474 DASHSCOPE_TOKEN_PLAN_ORIGIN,
1475 DASHSCOPE_CHAT_PATH,
1476 CatalogSourceKind::QwenCatalog,
1477 BillingAuthorityClass::QwenMeteredApi,
1478 ModelNamespace::Qwen,
1479 ),
1480 (
1481 PhaseKind::GrokSubscription,
1482 ProviderService::Grok,
1483 XAI_ORIGIN,
1484 XAI_CHAT_PATH,
1485 CatalogSourceKind::GrokCatalog,
1486 BillingAuthorityClass::GrokSubscription,
1487 ModelNamespace::Grok,
1488 ),
1489 (
1490 PhaseKind::GrokApi,
1491 ProviderService::Grok,
1492 XAI_ORIGIN,
1493 XAI_CHAT_PATH,
1494 CatalogSourceKind::GrokCatalog,
1495 BillingAuthorityClass::GrokMeteredApi,
1496 ModelNamespace::Grok,
1497 ),
1498 (
1499 PhaseKind::ZaiSubscription,
1500 ProviderService::Zai,
1501 ZAI_ORIGIN,
1502 ZAI_CHAT_PATH,
1503 CatalogSourceKind::ZaiCatalog,
1504 BillingAuthorityClass::ZaiSubscription,
1505 ModelNamespace::Zai,
1506 ),
1507 (
1508 PhaseKind::ZaiApi,
1509 ProviderService::Zai,
1510 ZAI_ORIGIN,
1511 ZAI_CHAT_PATH,
1512 CatalogSourceKind::ZaiCatalog,
1513 BillingAuthorityClass::ZaiMeteredApi,
1514 ModelNamespace::Zai,
1515 ),
1516 (
1517 PhaseKind::KimiSubscription,
1518 ProviderService::MoonshotKimi,
1519 MOONSHOT_ORIGIN,
1520 MOONSHOT_CHAT_PATH,
1521 CatalogSourceKind::KimiCatalog,
1522 BillingAuthorityClass::KimiSubscription,
1523 ModelNamespace::MoonshotKimi,
1524 ),
1525 (
1526 PhaseKind::KimiApi,
1527 ProviderService::MoonshotKimi,
1528 MOONSHOT_ORIGIN,
1529 MOONSHOT_CHAT_PATH,
1530 CatalogSourceKind::KimiCatalog,
1531 BillingAuthorityClass::KimiMeteredApi,
1532 ModelNamespace::MoonshotKimi,
1533 ),
1534 (
1535 PhaseKind::DeepseekApi,
1536 ProviderService::Deepseek,
1537 DEEPSEEK_ORIGIN,
1538 DEEPSEEK_CHAT_PATH,
1539 CatalogSourceKind::DeepseekCatalog,
1540 BillingAuthorityClass::DeepseekMeteredApi,
1541 ModelNamespace::Deepseek,
1542 ),
1543 (
1544 PhaseKind::ClaudeSubscription,
1545 ProviderService::Claude,
1546 ANTHROPIC_ORIGIN,
1547 ANTHROPIC_CHAT_PATH,
1548 CatalogSourceKind::ClaudeCatalog,
1549 BillingAuthorityClass::ClaudeSubscription,
1550 ModelNamespace::Claude,
1551 ),
1552 (
1553 PhaseKind::ClaudeApi,
1554 ProviderService::Claude,
1555 ANTHROPIC_ORIGIN,
1556 ANTHROPIC_CHAT_PATH,
1557 CatalogSourceKind::ClaudeCatalog,
1558 BillingAuthorityClass::ClaudeMeteredApi,
1559 ModelNamespace::Claude,
1560 ),
1561 (
1562 PhaseKind::GeminiSubscription,
1563 ProviderService::Gemini,
1564 GEMINI_ORIGIN,
1565 GEMINI_GENERATE_CONTENT_PATH,
1566 CatalogSourceKind::GeminiCatalog,
1567 BillingAuthorityClass::GeminiSubscription,
1568 ModelNamespace::Gemini,
1569 ),
1570 (
1571 PhaseKind::GeminiApi,
1572 ProviderService::Gemini,
1573 GEMINI_ORIGIN,
1574 GEMINI_GENERATE_CONTENT_PATH,
1575 CatalogSourceKind::GeminiCatalog,
1576 BillingAuthorityClass::GeminiMeteredApi,
1577 ModelNamespace::Gemini,
1578 ),
1579 ];
1580 for (phase, provider, origin, path, catalog, billing, namespace) in cases {
1581 let identity =
1582 follow_on_identity(phase, provider, origin, path, catalog, billing, namespace);
1583 assert!(identity.validate().is_ok(), "{phase:?} should validate");
1584 assert!(identity.phase.is_builtin(), "{phase:?} is first-class");
1585 assert_eq!(
1586 identity.phase.multi_agent_capability(),
1587 MultiAgentCapability::NamespaceUnsupported
1588 );
1589 assert_eq!(
1590 identity
1591 .multi_agent_v2_projection()
1592 .observed_namespace_calls,
1593 ObservedNamespaceCallBehavior::BareNameNoNamespace
1594 );
1595 assert_eq!(identity.multi_agent_version_served(), MultiAgentVersion::V2);
1596 assert_eq!(
1597 identity.mav2_namespace_choice(),
1598 MultiAgentNamespace::Agents
1599 );
1600 }
1601 }
1602
1603 #[test]
1604 fn claude_routes_validate_with_verified_anthropic_wire_contract() {
1605 for (phase, billing) in [
1613 (
1614 PhaseKind::ClaudeSubscription,
1615 BillingAuthorityClass::ClaudeSubscription,
1616 ),
1617 (
1618 PhaseKind::ClaudeApi,
1619 BillingAuthorityClass::ClaudeMeteredApi,
1620 ),
1621 ] {
1622 let identity = follow_on_identity(
1623 phase,
1624 ProviderService::Claude,
1625 ANTHROPIC_ORIGIN,
1626 ANTHROPIC_CHAT_PATH,
1627 CatalogSourceKind::ClaudeCatalog,
1628 billing,
1629 ModelNamespace::Claude,
1630 );
1631 assert!(identity.validate().is_ok());
1632 assert!(identity.phase.is_builtin(), "Claude is first-class");
1633 assert_eq!(
1634 identity.multi_agent_v2_projection(),
1635 MultiAgentCapabilityProjection {
1636 namespace_tools: false,
1637 multi_agent_version: MultiAgentVersion::V2,
1638 wire_api: MultiAgentWireApi::Responses,
1639 observed_namespace_calls: ObservedNamespaceCallBehavior::BareNameNoNamespace,
1640 }
1641 );
1642 assert_eq!(
1643 identity.mav2_namespace_choice(),
1644 MultiAgentNamespace::Agents
1645 );
1646 }
1647
1648 assert_eq!(ANTHROPIC_ORIGIN, "https://api.anthropic.com");
1650 assert_eq!(ANTHROPIC_CHAT_PATH, "/v1/messages");
1651 assert_eq!(ANTHROPIC_API_KEY_HEADER, "x-api-key");
1652 assert_eq!(ANTHROPIC_VERSION_HEADER, "anthropic-version");
1653 assert_eq!(ANTHROPIC_VERSION, "2023-06-01");
1654 assert_eq!(PhaseId::CLAUDE_SUBSCRIPTION, "claude_subscription");
1655 assert_eq!(PhaseId::CLAUDE_API, "claude_api");
1656
1657 let mut wrong_origin = follow_on_identity(
1659 PhaseKind::ClaudeApi,
1660 ProviderService::Claude,
1661 ANTHROPIC_ORIGIN,
1662 ANTHROPIC_CHAT_PATH,
1663 CatalogSourceKind::ClaudeCatalog,
1664 BillingAuthorityClass::ClaudeMeteredApi,
1665 ModelNamespace::Claude,
1666 );
1667 wrong_origin.endpoint = EndpointIdentity {
1668 origin: "https://api.anthropic.example.com".to_owned(),
1669 path: ANTHROPIC_CHAT_PATH.to_owned(),
1670 };
1671 assert!(wrong_origin.validate().is_err());
1672 let mut wrong_billing = follow_on_identity(
1673 PhaseKind::ClaudeApi,
1674 ProviderService::Claude,
1675 ANTHROPIC_ORIGIN,
1676 ANTHROPIC_CHAT_PATH,
1677 CatalogSourceKind::ClaudeCatalog,
1678 BillingAuthorityClass::ClaudeMeteredApi,
1679 ModelNamespace::Claude,
1680 );
1681 wrong_billing.billing_authority = BillingAuthorityClass::ClaudeSubscription;
1682 assert!(wrong_billing.validate().is_err());
1683 }
1684
1685 #[test]
1686 fn gemini_routes_and_verified_generate_content_wire_contract() {
1687 for (phase, billing) in [
1694 (
1695 PhaseKind::GeminiSubscription,
1696 BillingAuthorityClass::GeminiSubscription,
1697 ),
1698 (
1699 PhaseKind::GeminiApi,
1700 BillingAuthorityClass::GeminiMeteredApi,
1701 ),
1702 ] {
1703 let identity = follow_on_identity(
1704 phase,
1705 ProviderService::Gemini,
1706 GEMINI_ORIGIN,
1707 GEMINI_GENERATE_CONTENT_PATH,
1708 CatalogSourceKind::GeminiCatalog,
1709 billing,
1710 ModelNamespace::Gemini,
1711 );
1712 assert!(identity.validate().is_ok());
1713 assert!(identity.phase.is_builtin(), "Gemini is first-class");
1714 assert_eq!(
1715 identity.multi_agent_v2_projection(),
1716 MultiAgentCapabilityProjection {
1717 namespace_tools: false,
1718 multi_agent_version: MultiAgentVersion::V2,
1719 wire_api: MultiAgentWireApi::Responses,
1720 observed_namespace_calls: ObservedNamespaceCallBehavior::BareNameNoNamespace,
1721 }
1722 );
1723 assert_eq!(
1724 identity.mav2_namespace_choice(),
1725 MultiAgentNamespace::Agents
1726 );
1727 }
1728
1729 assert_eq!(GEMINI_ORIGIN, "https://generativelanguage.googleapis.com");
1732 assert_eq!(
1733 GEMINI_GENERATE_CONTENT_PATH,
1734 "/v1beta/models/{model}:generateContent"
1735 );
1736 assert_eq!(GEMINI_API_KEY_HEADER, "x-goog-api-key");
1737 assert_eq!(PhaseId::GEMINI_SUBSCRIPTION, "gemini_subscription");
1738 assert_eq!(PhaseId::GEMINI_API, "gemini_api");
1739
1740 let mut wrong_origin = follow_on_identity(
1743 PhaseKind::GeminiApi,
1744 ProviderService::Gemini,
1745 GEMINI_ORIGIN,
1746 GEMINI_GENERATE_CONTENT_PATH,
1747 CatalogSourceKind::GeminiCatalog,
1748 BillingAuthorityClass::GeminiMeteredApi,
1749 ModelNamespace::Gemini,
1750 );
1751 wrong_origin.endpoint.origin = "https://generativelanguage.example.com".to_owned();
1752 assert!(wrong_origin.validate().is_err());
1753 let mut wrong_path = follow_on_identity(
1754 PhaseKind::GeminiApi,
1755 ProviderService::Gemini,
1756 GEMINI_ORIGIN,
1757 GEMINI_GENERATE_CONTENT_PATH,
1758 CatalogSourceKind::GeminiCatalog,
1759 BillingAuthorityClass::GeminiMeteredApi,
1760 ModelNamespace::Gemini,
1761 );
1762 wrong_path.endpoint.path = "/v1beta/models/gemini-2.5-flash:generateContent".to_owned();
1763 assert!(
1764 wrong_path.validate().is_err(),
1765 "the concrete model path is a template the adapter materializes"
1766 );
1767 let mut wrong_billing = follow_on_identity(
1768 PhaseKind::GeminiApi,
1769 ProviderService::Gemini,
1770 GEMINI_ORIGIN,
1771 GEMINI_GENERATE_CONTENT_PATH,
1772 CatalogSourceKind::GeminiCatalog,
1773 BillingAuthorityClass::GeminiMeteredApi,
1774 ModelNamespace::Gemini,
1775 );
1776 wrong_billing.billing_authority = BillingAuthorityClass::GeminiSubscription;
1777 assert!(wrong_billing.validate().is_err());
1778 }
1779
1780 #[test]
1781 fn follow_on_phase_rejects_wrong_provider_or_billing() {
1782 let mut identity = follow_on_identity(
1783 PhaseKind::QwenApi,
1784 ProviderService::Qwen,
1785 DASHSCOPE_ORIGIN,
1786 DASHSCOPE_CHAT_PATH,
1787 CatalogSourceKind::QwenCatalog,
1788 BillingAuthorityClass::QwenMeteredApi,
1789 ModelNamespace::Qwen,
1790 );
1791 assert!(identity.validate().is_ok());
1792 identity.provider = ProviderService::Zai;
1793 assert!(identity.validate().is_err());
1794 let mut billing = follow_on_identity(
1795 PhaseKind::QwenApi,
1796 ProviderService::Qwen,
1797 DASHSCOPE_ORIGIN,
1798 DASHSCOPE_CHAT_PATH,
1799 CatalogSourceKind::QwenCatalog,
1800 BillingAuthorityClass::QwenMeteredApi,
1801 ModelNamespace::Qwen,
1802 );
1803 billing.billing_authority = BillingAuthorityClass::QwenSubscription;
1804 assert!(billing.validate().is_err());
1805 let mut missing = follow_on_identity(
1806 PhaseKind::KimiApi,
1807 ProviderService::MoonshotKimi,
1808 MOONSHOT_ORIGIN,
1809 MOONSHOT_CHAT_PATH,
1810 CatalogSourceKind::KimiCatalog,
1811 BillingAuthorityClass::KimiMeteredApi,
1812 ModelNamespace::MoonshotKimi,
1813 );
1814 missing.credential_ref = None;
1815 missing.credential_refs = Vec::new();
1816 assert!(missing.validate().is_err());
1817 }
1818
1819 #[test]
1820 fn deepseek_api_route_is_first_class_openai_compat() {
1821 let identity = follow_on_identity(
1825 PhaseKind::DeepseekApi,
1826 ProviderService::Deepseek,
1827 DEEPSEEK_ORIGIN,
1828 DEEPSEEK_CHAT_PATH,
1829 CatalogSourceKind::DeepseekCatalog,
1830 BillingAuthorityClass::DeepseekMeteredApi,
1831 ModelNamespace::Deepseek,
1832 );
1833 assert!(identity.validate().is_ok());
1834 assert!(identity.phase.is_builtin(), "DeepSeek API is first-class");
1835 assert_eq!(
1836 identity.phase.multi_agent_capability(),
1837 MultiAgentCapability::NamespaceUnsupported
1838 );
1839 assert_eq!(
1840 identity.multi_agent_v2_projection(),
1841 MultiAgentCapabilityProjection {
1842 namespace_tools: false,
1843 multi_agent_version: MultiAgentVersion::V2,
1844 wire_api: MultiAgentWireApi::Responses,
1845 observed_namespace_calls: ObservedNamespaceCallBehavior::BareNameNoNamespace,
1846 }
1847 );
1848 assert_eq!(
1849 identity.mav2_namespace_choice(),
1850 MultiAgentNamespace::Agents
1851 );
1852
1853 assert_eq!(DEEPSEEK_ORIGIN, "https://api.deepseek.com");
1856 assert_eq!(DEEPSEEK_CHAT_PATH, "/chat/completions");
1857 assert_eq!(PhaseId::DEEPSEEK_API, "deepseek_api");
1858
1859 let mut wrong_origin = identity.clone();
1861 wrong_origin.endpoint = EndpointIdentity {
1862 origin: "https://api.deepseek.example.com".to_owned(),
1863 path: DEEPSEEK_CHAT_PATH.to_owned(),
1864 };
1865 assert!(wrong_origin.validate().is_err());
1866 let mut wrong_billing = identity;
1867 wrong_billing.billing_authority = BillingAuthorityClass::KimiMeteredApi;
1868 assert!(wrong_billing.validate().is_err());
1869 }
1870
1871 #[test]
1872 fn env_secret_refs_restrict_to_resolver_charset() {
1873 for invalid in ["env:has-dash", "env:a.b", "env:a/b", "env:"] {
1877 assert!(
1878 !valid_secret_ref(invalid),
1879 "{invalid} should be rejected as an env secret ref"
1880 );
1881 }
1882 assert!(valid_secret_ref("env:MY_VAR"));
1883 assert!(valid_secret_ref("env:STEADYMUX_FOLLOW_ON_KEY"));
1884 assert!(valid_secret_ref("env:A1_B2"));
1885 assert!(valid_secret_ref("keychain:service/account"));
1887 assert!(valid_secret_ref("command:fetch-token"));
1888 }
1889}