) : null}
diff --git a/ui/src/pages/secrets/MissingUserSecretsBanner.tsx b/ui/src/pages/secrets/MissingUserSecretsBanner.tsx
new file mode 100644
index 00000000000..68ebfe8521f
--- /dev/null
+++ b/ui/src/pages/secrets/MissingUserSecretsBanner.tsx
@@ -0,0 +1,106 @@
+import { useState } from "react";
+import { useQuery } from "@tanstack/react-query";
+import { AlertTriangle } from "lucide-react";
+import { Link } from "react-router-dom";
+import { Button } from "@/components/ui/button";
+import { secretsApi, type MyUserSecretEntry } from "../../api/secrets";
+import { queryKeys } from "../../lib/queryKeys";
+import { SetMyUserSecretDialog } from "./SetMyUserSecretDialog";
+
+/**
+ * Warning surface for user secrets the current user has not yet set. Renders
+ * nothing when there is nothing missing, so it is safe to embed on task
+ * creation / run and issue-failure surfaces. Lets the user satisfy a missing
+ * required secret inline via the shared value dialog.
+ *
+ * Pass `definitionKeys` to scope the warning to a specific set (e.g. the user
+ * secrets a blocked run reported as missing); omit it to warn about every
+ * active definition the user has not set.
+ */
+export function MissingUserSecretsBanner({
+ companyId,
+ definitionKeys,
+ title = "Set your user secrets",
+ secretsPath,
+ className,
+}: {
+ companyId: string;
+ definitionKeys?: string[];
+ title?: string;
+ /** Optional route to the Secrets → My secrets tab for the "Manage all" link. */
+ secretsPath?: string;
+ className?: string;
+}) {
+ const [dialogFor, setDialogFor] = useState(null);
+
+ const mySecretsQuery = useQuery({
+ queryKey: queryKeys.secrets.myUserSecrets(companyId),
+ queryFn: () => secretsApi.listMyUserSecrets(companyId),
+ retry: false,
+ });
+
+ const keyFilter = definitionKeys ? new Set(definitionKeys) : null;
+ const missing = (mySecretsQuery.data ?? []).filter(
+ (entry) =>
+ entry.definition.status === "active" &&
+ !entry.secret &&
+ (!keyFilter || keyFilter.has(entry.definition.key)),
+ );
+
+ if (missing.length === 0) return null;
+
+ return (
+
+
+
+
+
{title}
+
+ {missing.length} user secret{missing.length === 1 ? "" : "s"} you are responsible for
+ {missing.length === 1 ? " has" : " have"} no value yet. Runs that require
+ {missing.length === 1 ? " it" : " them"} will fail until you set your value.
+