Skip to main content

systemprompt_runtime/managed/
git_sources.rs

1//! Application-owned credential resolution for Git source synchronization.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::path::PathBuf;
7
8use super::OrchestrationError;
9use systemprompt_config::SecretsBootstrap;
10use systemprompt_identifiers::{ManagedSourceId, UserId};
11use systemprompt_marketplace::managed::{
12    GitSyncRequest, GitSyncResult, ManagedRepository, SourceSpec,
13};
14
15#[derive(Debug, Clone)]
16pub struct GitSourceOrchestrator {
17    managed: ManagedRepository,
18    scratch_root: PathBuf,
19}
20
21impl GitSourceOrchestrator {
22    pub const fn new(managed: ManagedRepository, scratch_root: PathBuf) -> Self {
23        Self {
24            managed,
25            scratch_root,
26        }
27    }
28
29    pub async fn synchronize(
30        &self,
31        owner: &UserId,
32        request: &GitSyncRequest,
33    ) -> Result<GitSyncResult, OrchestrationError> {
34        let credential = self.credential(owner, &request.source_id).await?;
35        Ok(self
36            .managed
37            .sync_git_source_with_credential(
38                owner,
39                request,
40                credential.as_deref(),
41                &self.scratch_root,
42            )
43            .await?)
44    }
45
46    async fn credential(
47        &self,
48        owner: &UserId,
49        source: &ManagedSourceId,
50    ) -> Result<Option<String>, OrchestrationError> {
51        match self.managed.get_source(owner, source).await? {
52            SourceSpec::Git {
53                credential_reference: Some(reference),
54                ..
55            } => {
56                let secrets =
57                    SecretsBootstrap::get().map_err(OrchestrationError::CredentialsUnavailable)?;
58                let credential = secrets
59                    .get(&reference)
60                    .filter(|value| !value.is_empty())
61                    .ok_or(OrchestrationError::CredentialUnresolved)?;
62                Ok(Some(credential.clone()))
63            },
64            SourceSpec::Git {
65                credential_reference: None,
66                ..
67            } => Ok(None),
68            _ => Err(OrchestrationError::NotGitSource),
69        }
70    }
71}