systemprompt_runtime/managed/
git_sources.rs1use super::OrchestrationError;
8use std::collections::BTreeMap;
9use systemprompt_config::SecretsBootstrap;
10use systemprompt_identifiers::{ManagedSourceId, UserId};
11use systemprompt_marketplace::managed::{
12 GitSyncRequest, GitSyncResult, ManagedRepository, SourceSpec,
13};
14use systemprompt_models::feedback::verification::{
15 DependencyVerificationManifest, DependencyVerificationRequest,
16};
17
18#[derive(Debug, Clone)]
19pub struct GitSourceOrchestrator {
20 managed: ManagedRepository,
21}
22
23impl GitSourceOrchestrator {
24 pub const fn new(managed: ManagedRepository) -> Self {
25 Self { managed }
26 }
27
28 pub async fn synchronize(
29 &self,
30 owner: &UserId,
31 request: &GitSyncRequest,
32 ) -> Result<GitSyncResult, OrchestrationError> {
33 let credential = self.credential(owner, &request.source_id).await?;
34 Ok(self
35 .managed
36 .sync_git_source_with_credential(owner, request, credential.as_deref())
37 .await?)
38 }
39
40 pub async fn verify(
41 &self,
42 owner: &UserId,
43 request: &DependencyVerificationRequest,
44 ) -> Result<DependencyVerificationManifest, OrchestrationError> {
45 request.validate().map_err(|error| {
46 OrchestrationError::Source(format!("Invalid dependency verification request: {error}"))
47 })?;
48 let mut credentials = BTreeMap::new();
49 for revision in &request.revisions {
50 if !credentials.contains_key(&revision.source_id)
51 && let Some(credential) = self.credential(owner, &revision.source_id).await?
52 {
53 credentials.insert(revision.source_id.clone(), credential);
54 }
55 }
56 Ok(self
57 .managed
58 .verify_git_dependencies(owner, request, &credentials)
59 .await?)
60 }
61
62 async fn credential(
63 &self,
64 owner: &UserId,
65 source: &ManagedSourceId,
66 ) -> Result<Option<String>, OrchestrationError> {
67 match self.managed.get_source(owner, source).await? {
68 SourceSpec::Git {
69 credential_reference: Some(reference),
70 ..
71 } => {
72 let secrets = SecretsBootstrap::get().map_err(|error| {
73 OrchestrationError::Source(format!("Git credentials are unavailable: {error}"))
74 })?;
75 let credential = secrets
76 .get(&reference)
77 .filter(|value| !value.is_empty())
78 .ok_or_else(|| {
79 OrchestrationError::Source(
80 "Git credential reference is unresolved".to_owned(),
81 )
82 })?;
83 Ok(Some(credential.clone()))
84 },
85 SourceSpec::Git {
86 credential_reference: None,
87 ..
88 } => Ok(None),
89 _ => Err(OrchestrationError::Source(
90 "Operation requires a registered Git source".to_owned(),
91 )),
92 }
93 }
94}