systemprompt_models/bridge/
manifest.rs1use std::collections::BTreeMap;
24
25use serde::{Deserialize, Serialize};
26
27pub use crate::bridge::ids::ManifestSignature;
28use crate::bridge::ids::{
29 LibraryArtifactId, ManagedMcpServerName, PluginId, Sha256Digest, SkillId, SkillName, ToolName,
30 ToolPolicy,
31};
32use crate::bridge::manifest_version::ManifestVersion;
33use crate::services::hooks::{HookCategory, HookEvent};
34use crate::services::plugin::{PluginComponentRef, PluginHooksRef};
35use systemprompt_identifiers::{AgentId, AgentName, HookId, TenantId, UserId, ValidatedUrl};
36
37pub const MANIFEST_SCHEMA_VERSION: u32 = 1;
38
39pub const MIN_BRIDGE_VERSION: &str = "0.28.0";
43
44#[must_use]
45pub fn bridge_version_is_supported(reported: &str, floor: &str) -> bool {
46 match (
47 semver::Version::parse(reported),
48 semver::Version::parse(floor),
49 ) {
50 (Ok(reported), Ok(floor)) => reported >= floor,
51 _ => true,
54 }
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct SignedManifestEnvelope {
59 pub payload: String,
60 pub signature: ManifestSignature,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct SignedManifest {
65 #[serde(default)]
66 pub min_schema_version: u32,
67 #[serde(default)]
68 pub min_bridge_version: Option<String>,
69 pub manifest_version: ManifestVersion,
70 pub issued_at: String,
71 pub not_before: String,
72 pub user_id: UserId,
73 pub tenant_id: Option<TenantId>,
74 #[serde(default)]
75 pub user: Option<UserInfo>,
76 pub plugins: Vec<PluginEntry>,
77 #[serde(default)]
78 pub skills: Vec<SkillEntry>,
79 #[serde(default)]
80 pub agents: Vec<AgentEntry>,
81 #[serde(default)]
82 pub hooks: Vec<HookEntry>,
83 pub managed_mcp_servers: Vec<ManagedMcpServer>,
84 pub revocations: Vec<String>,
85 #[serde(default)]
86 pub enabled_hosts: Vec<String>,
87 #[serde(default)]
88 pub host_model_protocols: BTreeMap<String, Vec<String>>,
89 #[serde(default)]
90 pub artifacts: Vec<ArtifactEntry>,
91 #[serde(default)]
92 pub allow_claude_ai_connectors: bool,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct UserInfo {
97 pub id: UserId,
98 pub name: String,
99 pub email: String,
100 #[serde(default)]
101 pub display_name: Option<String>,
102 #[serde(default)]
103 pub roles: Vec<String>,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct PluginEntry {
108 pub id: PluginId,
109 pub version: String,
110 pub sha256: Sha256Digest,
111 pub files: Vec<PluginFile>,
112 #[serde(default)]
113 pub hooks: PluginHooksRef,
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct PluginFile {
118 pub path: String,
119 pub sha256: Sha256Digest,
120 pub size: u64,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct ArtifactEntry {
127 pub id: LibraryArtifactId,
128 pub name: String,
129 pub description: String,
130 pub version: String,
131 pub mcp_tools: Vec<String>,
132 pub content: String,
133 pub starred: bool,
134 pub sha256: Sha256Digest,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct SkillEntry {
139 pub id: SkillId,
140 pub name: SkillName,
141 pub description: String,
142 pub file_path: String,
143 #[serde(default)]
144 pub tags: Vec<String>,
145 pub sha256: Sha256Digest,
146 pub instructions: String,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct AgentEntry {
151 pub id: AgentId,
152 pub name: AgentName,
153 pub display_name: String,
154 pub description: String,
155 pub version: String,
156 pub endpoint: String,
157 pub enabled: bool,
158 pub is_default: bool,
159 pub is_primary: bool,
160 #[serde(default)]
161 pub provider: Option<String>,
162 #[serde(default)]
163 pub model: Option<String>,
164 #[serde(default)]
165 pub mcp_servers: PluginComponentRef,
166 #[serde(default)]
167 pub skills: PluginComponentRef,
168 #[serde(default)]
169 pub tags: Vec<String>,
170 #[serde(default)]
171 pub system_prompt: Option<String>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct HookEntry {
176 pub id: HookId,
177 pub name: String,
178 pub description: String,
179 pub version: String,
180 pub event: HookEvent,
181 pub matcher: String,
182 pub command: String,
183 #[serde(default)]
184 pub is_async: bool,
185 pub category: HookCategory,
186 #[serde(default)]
187 pub tags: Vec<String>,
188 pub sha256: Sha256Digest,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct ManagedMcpServer {
193 pub name: ManagedMcpServerName,
194 pub url: ValidatedUrl,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub transport: Option<String>,
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub headers: Option<BTreeMap<String, String>>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub oauth: Option<bool>,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub tool_policy: Option<BTreeMap<ToolName, ToolPolicy>>,
203}