From 49c20b1f07d111bc20ff40c22263991c2cf88a06 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 5 May 2026 11:21:15 -0500 Subject: [PATCH] Surface all restored webhook secrets Co-Authored-By: Paperclip --- ui/src/components/RoutineHistoryTab.tsx | 4 +- ui/src/pages/RoutineDetail.tsx | 70 ++++++++++++++++--------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/ui/src/components/RoutineHistoryTab.tsx b/ui/src/components/RoutineHistoryTab.tsx index defba874744..0bae27142b7 100644 --- a/ui/src/components/RoutineHistoryTab.tsx +++ b/ui/src/components/RoutineHistoryTab.tsx @@ -113,8 +113,8 @@ export function RoutineHistoryTab({ pushToast({ title: `Restored revision ${restoredFromNumber} as revision ${newNumber}`, body: data.secretMaterials.length > 0 - ? "Paused triggers stay paused. New webhook secret available in the banner above." - : "Paused triggers stay paused.", + ? "Trigger enabled state was restored from the snapshot. New webhook secrets are available in the banner above." + : "Trigger enabled state was restored from the snapshot.", tone: "success", }); onRestoreSecretMaterials(data); diff --git a/ui/src/pages/RoutineDetail.tsx b/ui/src/pages/RoutineDetail.tsx index 047d515f446..a8a0e9d0e51 100644 --- a/ui/src/pages/RoutineDetail.tsx +++ b/ui/src/pages/RoutineDetail.tsx @@ -91,8 +91,10 @@ type RoutineTab = (typeof routineTabs)[number]; type SecretMessage = { title: string; - webhookUrl: string; - webhookSecret: string; + entries: Array<{ + webhookUrl: string; + webhookSecret: string; + }>; }; function autoResizeTextarea(element: HTMLTextAreaElement | null) { @@ -571,8 +573,10 @@ export function RoutineDetail() { if (result.secretMaterial) { setSecretMessage({ title: "Webhook trigger created", - webhookUrl: result.secretMaterial.webhookUrl, - webhookSecret: result.secretMaterial.webhookSecret, + entries: [{ + webhookUrl: result.secretMaterial.webhookUrl, + webhookSecret: result.secretMaterial.webhookSecret, + }], }); } else { pushToast({ @@ -646,8 +650,10 @@ export function RoutineDetail() { onSuccess: async (result) => { setSecretMessage({ title: "Webhook secret rotated", - webhookUrl: result.secretMaterial.webhookUrl, - webhookSecret: result.secretMaterial.webhookSecret, + entries: [{ + webhookUrl: result.secretMaterial.webhookUrl, + webhookSecret: result.secretMaterial.webhookSecret, + }], }); await Promise.all([ queryClient.invalidateQueries({ queryKey: queryKeys.routines.detail(routineId!) }), @@ -815,21 +821,30 @@ export function RoutineDetail() {

{secretMessage.title}

Save this now. Paperclip will not show the secret value again.

-
-
- - -
-
- - -
+
+ {secretMessage.entries.map((entry, index) => ( +
+ {secretMessage.entries.length > 1 && ( +

+ Webhook trigger {index + 1} of {secretMessage.entries.length} +

+ )} +
+ + +
+
+ + +
+
+ ))}
)} @@ -1227,12 +1242,15 @@ export function RoutineDetail() { agents={agentById} projects={projectById} onRestoreSecretMaterials={(response: RestoreRoutineRevisionResponse) => { - const recreated = response.secretMaterials[0]; - if (recreated) { + if (response.secretMaterials.length > 0) { setSecretMessage({ - title: "Webhook trigger restored", - webhookUrl: recreated.webhookUrl, - webhookSecret: recreated.webhookSecret, + title: response.secretMaterials.length === 1 + ? "Webhook trigger restored" + : `${response.secretMaterials.length} webhook triggers restored`, + entries: response.secretMaterials.map((recreated) => ({ + webhookUrl: recreated.webhookUrl, + webhookSecret: recreated.webhookSecret, + })), }); } }}