Keep snapshot imports on validated relay

Co-authored-by: npub102wg7q285p64ch2fjvstmf2ntn2sz3c4u5hmwatalc76mhsuauysftjtfj <7a9c8f0147a0755c5d499320bda5535cd5014715e52fb7757dfe3dadde1cef09@buzz.block.builderlab.xyz>
Signed-off-by: npub102wg7q285p64ch2fjvstmf2ntn2sz3c4u5hmwatalc76mhsuauysftjtfj <7a9c8f0147a0755c5d499320bda5535cd5014715e52fb7757dfe3dadde1cef09@buzz.block.builderlab.xyz>
This commit is contained in:
7a9c8f0147a0755c5d499320bda5535cd5014715e52fb7757dfe3dadde1cef09@buzz.block.builderlab.xyz
2026-07-23 13:57:01 -07:00
parent adbc1112da
commit eb7354dd80
4 changed files with 79 additions and 35 deletions
@@ -288,18 +288,21 @@ pub async fn preview_agent_snapshot_import(
.map_err(|e| format!("spawn_blocking failed: {e}"))?
}
pub(super) fn validate_snapshot_import_relay_with<F>(
workspace_relay_url: &str,
pub(super) fn validated_snapshot_import_relay_with<R, F>(
read_workspace_relay: R,
validate: F,
) -> Result<(), String>
) -> Result<String, String>
where
R: FnOnce() -> String,
F: FnOnce(&crate::managed_agents::BackendKind, &str, &str) -> Result<(), String>,
{
let workspace_relay_url = read_workspace_relay();
validate(
&crate::managed_agents::BackendKind::Local,
"",
workspace_relay_url,
)
&workspace_relay_url,
)?;
Ok(workspace_relay_url)
}
// ── `confirm_agent_snapshot_import` ──────────────────────────────────────────
@@ -337,10 +340,12 @@ pub async fn confirm_agent_snapshot_import(
// Snapshot imports always mint a local agent with an empty relay pin. Reject
// a disallowed effective workspace relay before key generation or store I/O.
let workspace_relay_url = relay_ws_url_with_override(&state);
validate_snapshot_import_relay_with(&workspace_relay_url, |backend, pin, workspace| {
crate::managed_agents::validate_effective_local_agent_relay(backend, pin, workspace)
})?;
let workspace_relay_url = validated_snapshot_import_relay_with(
|| relay_ws_url_with_override(&state),
|backend, pin, workspace| {
crate::managed_agents::validate_effective_local_agent_relay(backend, pin, workspace)
},
)?;
// ── Resolve behavioral defaults ──────────────────────────────────────────
let minted = resolve_snapshot_import_behavior(
@@ -527,8 +532,7 @@ pub async fn confirm_agent_snapshot_import(
};
// ── Phase 3b: publish kind:0 profile (async, outside lock) ───────────────
let relay_url =
effective_agent_relay_url(&record.relay_url, &relay_ws_url_with_override(&state));
let relay_url = effective_agent_relay_url(&record.relay_url, &workspace_relay_url);
let profile_sync_error = sync_managed_agent_profile(
&state,
&relay_url,
@@ -1,6 +1,6 @@
use super::import::{
decode_snapshot_from_bytes, reject_legacy_persona_filename, resolve_snapshot_import_behavior,
validate_snapshot_import_relay_with, AgentSnapshotImportResult, MAX_SNAPSHOT_JSON_BYTES,
validated_snapshot_import_relay_with, AgentSnapshotImportResult, MAX_SNAPSHOT_JSON_BYTES,
MAX_SNAPSHOT_PNG_BYTES,
};
use super::*;
@@ -972,16 +972,27 @@ fn validate_encode_size_png_over_boundary_is_rejected() {
}
#[test]
fn individual_snapshot_import_preflights_empty_pin_before_mint_or_store() {
let calls = std::cell::Cell::new(0);
let result =
validate_snapshot_import_relay_with("wss://public.example", |backend, pin, relay| {
calls.set(calls.get() + 1);
fn individual_snapshot_import_carries_the_validated_relay_snapshot_to_io() {
let reads = std::cell::Cell::new(0);
let relay = validated_snapshot_import_relay_with(
|| {
reads.set(reads.get() + 1);
"wss://allowed.example".into()
},
|backend, pin, relay| {
assert_eq!(backend, &BackendKind::Local);
assert!(pin.is_empty());
assert_eq!(relay, "wss://public.example");
Err("blocked before mutation".into())
});
assert_eq!(result.unwrap_err(), "blocked before mutation");
assert_eq!(calls.get(), 1);
assert_eq!(relay, "wss://allowed.example");
Ok(())
},
)
.unwrap();
assert_eq!(relay, "wss://allowed.example");
assert_eq!(reads.get(), 1);
let blocked = validated_snapshot_import_relay_with(
|| "wss://public.example".into(),
|_, _, _| Err("blocked before mutation".into()),
);
assert_eq!(blocked.unwrap_err(), "blocked before mutation");
}
+16 -10
View File
@@ -496,18 +496,21 @@ pub async fn preview_team_snapshot_import(
///
/// Importing the same file twice yields two distinct teams with different
/// agent keypairs (same as individual agent import).
fn validate_team_snapshot_import_relay_with<F>(
workspace_relay_url: &str,
fn validated_team_snapshot_import_relay_with<R, F>(
read_workspace_relay: R,
validate: F,
) -> Result<(), String>
) -> Result<String, String>
where
R: FnOnce() -> String,
F: FnOnce(&crate::managed_agents::BackendKind, &str, &str) -> Result<(), String>,
{
let workspace_relay_url = read_workspace_relay();
validate(
&crate::managed_agents::BackendKind::Local,
"",
workspace_relay_url,
)
&workspace_relay_url,
)?;
Ok(workspace_relay_url)
}
#[tauri::command]
@@ -522,10 +525,12 @@ pub async fn confirm_team_snapshot_import(
// Team snapshots mint only empty-pin local agents. Preflight the workspace
// relay once before generating any member key or mutating any store.
let workspace_relay_url = relay_ws_url_with_override(&state);
validate_team_snapshot_import_relay_with(&workspace_relay_url, |backend, pin, workspace| {
crate::managed_agents::validate_effective_local_agent_relay(backend, pin, workspace)
})?;
let workspace_relay_url = validated_team_snapshot_import_relay_with(
|| relay_ws_url_with_override(&state),
|backend, pin, workspace| {
crate::managed_agents::validate_effective_local_agent_relay(backend, pin, workspace)
},
)?;
// Resolve behavioral defaults for every member before any key generation.
let definitions = build_import_definitions(&snapshot, input.keep_allowlist, &now)?;
@@ -775,7 +780,8 @@ pub async fn confirm_team_snapshot_import(
};
// ── Phase 4 & 5: profile sync + memory restore (async, outside lock) ────
let relay_ws = relay_ws_url_with_override(&state);
// Use the relay snapshot validated before mint/store for all agent-keyed I/O.
let relay_ws = workspace_relay_url;
let mut member_results: Vec<TeamSnapshotImportMemberResult> = Vec::with_capacity(minted.len());
for (m, snap_member) in minted.iter().zip(snapshot.members.iter()) {
@@ -725,17 +725,40 @@ fn full_rollback_at_teams_boundary_absent_agents_store() {
assert_eq!(errors.len(), 1, "only the teams-write error");
}
#[test]
fn team_snapshot_import_carries_the_validated_relay_snapshot_to_io() {
let workspace_reads = std::cell::Cell::new(0);
let validated_relay = validated_team_snapshot_import_relay_with(
|| {
workspace_reads.set(workspace_reads.get() + 1);
"wss://allowed.example".to_string()
},
|backend, pin, relay| {
assert_eq!(backend, &crate::managed_agents::BackendKind::Local);
assert!(pin.is_empty());
assert_eq!(relay, "wss://allowed.example");
Ok(())
},
)
.unwrap();
assert_eq!(validated_relay, "wss://allowed.example");
assert_eq!(workspace_reads.get(), 1);
}
#[test]
fn team_snapshot_import_preflights_empty_pin_once_before_mint_or_store() {
let calls = std::cell::Cell::new(0);
let result =
validate_team_snapshot_import_relay_with("wss://public.example", |backend, pin, relay| {
let result = validated_team_snapshot_import_relay_with(
|| "wss://public.example".to_string(),
|backend, pin, relay| {
calls.set(calls.get() + 1);
assert_eq!(backend, &crate::managed_agents::BackendKind::Local);
assert!(pin.is_empty());
assert_eq!(relay, "wss://public.example");
Err("blocked before mutation".into())
});
},
);
assert_eq!(result.unwrap_err(), "blocked before mutation");
assert_eq!(calls.get(), 1);
}