@@ -201,25 +201,56 @@ class ExpectedOutputSchema(BlockSchema):
201201@pytest .mark .asyncio (loop_scope = "session" )
202202async def test_clean_graph (server : SpinTestServer ):
203203 """
204- Test the clean_graph function that:
205- 1. Clears input block values
206- 2. Removes credentials from nodes
204+ Test the stripped_for_export function that:
205+ 1. Removes sensitive/secret fields from node inputs
206+ 2. Removes webhook information
207+ 3. Preserves non-sensitive data including input block values
207208 """
208- # Create a graph with input blocks and credentials
209+ # Create a graph with input blocks containing both sensitive and normal data
209210 graph = Graph (
210211 id = "test_clean_graph" ,
211212 name = "Test Clean Graph" ,
212213 description = "Test graph cleaning" ,
213214 nodes = [
214215 Node (
215- id = "input_node" ,
216216 block_id = AgentInputBlock ().id ,
217217 input_default = {
218+ "_test_id" : "input_node" ,
218219 "name" : "test_input" ,
219- "value" : "test value" ,
220+ "value" : "test value" , # This should be preserved
220221 "description" : "Test input description" ,
221222 },
222223 ),
224+ Node (
225+ block_id = AgentInputBlock ().id ,
226+ input_default = {
227+ "_test_id" : "input_node_secret" ,
228+ "name" : "secret_input" ,
229+ "value" : "another value" ,
230+ "secret" : True , # This makes the input secret
231+ },
232+ ),
233+ Node (
234+ block_id = StoreValueBlock ().id ,
235+ input_default = {
236+ "_test_id" : "node_with_secrets" ,
237+ "input" : "normal_value" ,
238+ "control_test_input" : "should be preserved" ,
239+ "api_key" : "secret_api_key_123" , # Should be filtered
240+ "password" : "secret_password_456" , # Should be filtered
241+ "token" : "secret_token_789" , # Should be filtered
242+ "credentials" : { # Should be filtered
243+ "id" : "fake-github-credentials-id" ,
244+ "provider" : "github" ,
245+ "type" : "api_key" ,
246+ },
247+ "anthropic_credentials" : { # Should be filtered
248+ "id" : "fake-anthropic-credentials-id" ,
249+ "provider" : "anthropic" ,
250+ "type" : "api_key" ,
251+ },
252+ },
253+ ),
223254 ],
224255 links = [],
225256 )
@@ -231,15 +262,54 @@ async def test_clean_graph(server: SpinTestServer):
231262 )
232263
233264 # Clean the graph
234- created_graph = await server .agent_server .test_get_graph (
265+ cleaned_graph = await server .agent_server .test_get_graph (
235266 created_graph .id , created_graph .version , DEFAULT_USER_ID , for_export = True
236267 )
237268
238- # # Verify input block value is cleared
269+ # Verify sensitive fields are removed but normal fields are preserved
239270 input_node = next (
240- n for n in created_graph .nodes if n .block_id == AgentInputBlock ().id
271+ n for n in cleaned_graph .nodes if n .input_default ["_test_id" ] == "input_node"
272+ )
273+
274+ # Non-sensitive fields should be preserved
275+ assert input_node .input_default ["name" ] == "test_input"
276+ assert input_node .input_default ["value" ] == "test value" # Should be preserved now
277+ assert input_node .input_default ["description" ] == "Test input description"
278+
279+ # Sensitive fields should be filtered out
280+ assert "api_key" not in input_node .input_default
281+ assert "password" not in input_node .input_default
282+
283+ # Verify secret input node preserves non-sensitive fields but removes secret value
284+ secret_node = next (
285+ n
286+ for n in cleaned_graph .nodes
287+ if n .input_default ["_test_id" ] == "input_node_secret"
288+ )
289+ assert secret_node .input_default ["name" ] == "secret_input"
290+ assert "value" not in secret_node .input_default # Secret default should be removed
291+ assert secret_node .input_default ["secret" ] is True
292+
293+ # Verify sensitive fields are filtered from nodes with secrets
294+ secrets_node = next (
295+ n
296+ for n in cleaned_graph .nodes
297+ if n .input_default ["_test_id" ] == "node_with_secrets"
241298 )
242- assert input_node .input_default ["value" ] == ""
299+ # Normal fields should be preserved
300+ assert secrets_node .input_default ["input" ] == "normal_value"
301+ assert secrets_node .input_default ["control_test_input" ] == "should be preserved"
302+ # Sensitive fields should be filtered out
303+ assert "api_key" not in secrets_node .input_default
304+ assert "password" not in secrets_node .input_default
305+ assert "token" not in secrets_node .input_default
306+ assert "credentials" not in secrets_node .input_default
307+ assert "anthropic_credentials" not in secrets_node .input_default
308+
309+ # Verify webhook info is removed (if any nodes had it)
310+ for node in cleaned_graph .nodes :
311+ assert node .webhook_id is None
312+ assert node .webhook is None
243313
244314
245315@pytest .mark .asyncio (loop_scope = "session" )
0 commit comments