"use client"; import { useEffect, useState } from "react"; import { Lock, Plus } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { CredentialForm, CredentialRow, } from "@/components/credentials/credential-form"; import { api, type PublicCredential } from "@/lib/api"; export default function CredentialsPage() { const [creds, setCreds] = useState(null); const [adding, setAdding] = useState(false); const [editingName, setEditingName] = useState(null); const [error, setError] = useState(null); async function refresh() { setError(null); try { const list = await api.listGlobalCredentials(); setCreds(list); } catch (e) { setError(e instanceof Error ? e.message : "load failed"); } } useEffect(() => { refresh(); }, []); async function handleDelete(name: string) { if (!confirm(`Delete credential "${name}"? Pipelines that reference it will fail until replaced (unless an agent override exists).`)) return; try { await api.deleteGlobalCredential(name); await refresh(); } catch (e) { setError(e instanceof Error ? e.message : "delete failed"); } } return (

Credentials

Org-wide credentials referenced by Deploy and other nodes. Available to every agent. Per-agent overrides live on the agent page.

{error && (

{error}

)}
Stored credentials Secret values (GCP service-account JSON, kv values) are AES-GCM encrypted at rest with FLOW_SECRET_KEY. The API never returns them — list shows only metadata + key names.
{creds === null && (

Loading…

)} {!adding && creds?.length === 0 && (

No credentials yet. Add one (e.g. aws) and reference it by name from a Deploy node.

)} {creds?.map((c) => (
{editingName === c.name ? ( setEditingName(null)} onSubmit={async (body) => { await api.updateGlobalCredential(c.name, body); setEditingName(null); await refresh(); }} onError={setError} /> ) : ( setEditingName(c.name)} onDelete={() => handleDelete(c.name)} /> )}
))} {adding && (
setAdding(false)} onSubmit={async (body) => { await api.createGlobalCredential(body); setAdding(false); await refresh(); }} onError={setError} />
)}
); }