fix: remove config bundle restore dependency
This commit is contained in:
@@ -33,7 +33,8 @@ pub use manifest::{
|
||||
};
|
||||
pub use model_client::{ProviderError, build_client};
|
||||
pub use prompt::catalog::{
|
||||
CatalogError, EffectivePromptCatalog, PromptCatalog, WorkerPrompt, prompt_schema_source,
|
||||
CatalogError, EffectivePromptCatalog, PromptCatalog, WorkerPrompt, WorkspacePromptProjection,
|
||||
prompt_schema_source,
|
||||
};
|
||||
pub use prompt::source::PromptCatalogSource;
|
||||
pub use prompt::system::{SystemPromptContext, SystemPromptError, SystemPromptTemplate};
|
||||
|
||||
@@ -171,6 +171,77 @@ pub enum CatalogError {
|
||||
DigestMismatch { expected: String, actual: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct WorkspacePromptProjection {
|
||||
pub workspace_id: String,
|
||||
pub config_revision: u64,
|
||||
pub source_digest: String,
|
||||
pub projection_digest: String,
|
||||
pub schema_fingerprint: String,
|
||||
pub toolchain_fingerprint: String,
|
||||
pub catalog: EffectivePromptCatalog,
|
||||
}
|
||||
|
||||
impl WorkspacePromptProjection {
|
||||
pub fn new(
|
||||
workspace_id: impl Into<String>,
|
||||
source_digest: impl Into<String>,
|
||||
projection_digest: impl Into<String>,
|
||||
catalog: EffectivePromptCatalog,
|
||||
) -> Result<Self, CatalogError> {
|
||||
let workspace_id = workspace_id.into();
|
||||
let source_digest = source_digest.into();
|
||||
let projection_digest = projection_digest.into();
|
||||
catalog.verify_digest()?;
|
||||
if workspace_id.trim().is_empty() {
|
||||
return Err(CatalogError::InvalidTemplateCatalog(
|
||||
"Workspace Prompt projection workspace_id must not be empty".to_string(),
|
||||
));
|
||||
}
|
||||
if source_digest.trim().is_empty() {
|
||||
return Err(CatalogError::InvalidTemplateCatalog(
|
||||
"Workspace Prompt projection source digest must not be empty".to_string(),
|
||||
));
|
||||
}
|
||||
if projection_digest.trim().is_empty() {
|
||||
return Err(CatalogError::InvalidTemplateCatalog(
|
||||
"Workspace Prompt projection digest must not be empty".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
workspace_id,
|
||||
config_revision: catalog.config_revision,
|
||||
source_digest,
|
||||
projection_digest,
|
||||
schema_fingerprint: catalog.schema_fingerprint.clone(),
|
||||
toolchain_fingerprint: catalog.toolchain_fingerprint.clone(),
|
||||
catalog,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn catalog(&self) -> &EffectivePromptCatalog {
|
||||
&self.catalog
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), CatalogError> {
|
||||
let rebuilt = Self::new(
|
||||
self.workspace_id.clone(),
|
||||
self.source_digest.clone(),
|
||||
self.projection_digest.clone(),
|
||||
self.catalog.clone(),
|
||||
)?;
|
||||
if rebuilt.config_revision != self.config_revision
|
||||
|| rebuilt.schema_fingerprint != self.schema_fingerprint
|
||||
|| rebuilt.toolchain_fingerprint != self.toolchain_fingerprint
|
||||
{
|
||||
return Err(CatalogError::InvalidTemplateCatalog(
|
||||
"Workspace Prompt projection metadata does not match its catalog".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PromptCatalog {
|
||||
env: Environment<'static>,
|
||||
projection: EffectivePromptCatalog,
|
||||
@@ -550,6 +621,32 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_prompt_projection_round_trips_and_rejects_tampered_metadata() {
|
||||
let catalog = EffectivePromptCatalog::new(
|
||||
BTreeMap::from([("default".to_string(), "PROMPT".to_string())]),
|
||||
8,
|
||||
"schema",
|
||||
"toolchain",
|
||||
)
|
||||
.unwrap();
|
||||
let projection = WorkspacePromptProjection::new(
|
||||
"workspace-a",
|
||||
"source-digest",
|
||||
catalog.catalog_digest.clone(),
|
||||
catalog,
|
||||
)
|
||||
.unwrap();
|
||||
let serialized = serde_json::to_string(&projection).unwrap();
|
||||
let restored: WorkspacePromptProjection = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(restored, projection);
|
||||
restored.validate().unwrap();
|
||||
|
||||
let mut tampered = restored;
|
||||
tampered.config_revision += 1;
|
||||
assert!(tampered.validate().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalog_source_preserves_workspace_projection_for_subworkers() {
|
||||
let templates = BTreeMap::from([("template".to_string(), "OVERRIDE".to_string())]);
|
||||
|
||||
Reference in New Issue
Block a user