import { useState } from "react"; import { LuPencil, LuPlus, LuTrash2, LuX } from "react-icons/lu"; import { errorMessage } from "../api/client.js"; import { useDeleteSecret, useOwners, useSecrets, useUpsertSecret, } from "../api/hooks.js"; import { formatTime } from "../lib/format.jsx"; export function SecretsPage() { const { data: owners = [] } = useOwners(); const [ownerFilter, setOwnerFilter] = useState(""); const { data: secrets = [], isLoading } = useSecrets(ownerFilter || undefined); const upsert = useUpsertSecret(); const del = useDeleteSecret(); const [mode, setMode] = useState(null); const [form, setForm] = useState({ owner: "", name: "", value: "", }); const [confirmDelete, setConfirmDelete] = useState(null); function openAdd() { setMode("add"); setForm({ owner: ownerFilter || owners[0] || "default", name: "", value: "", }); } function openReplace(s) { setMode("replace"); setForm({ owner: s.owner, name: s.name, value: "" }); } function closeForm() { setMode(null); setForm({ owner: "", name: "", value: "" }); } function onSubmit(e) { e.preventDefault(); upsert.mutate( { owner: form.owner, name: form.name, value: form.value }, { onSuccess: closeForm }, ); } return (

Secrets

{isLoading ? ( ) : secrets.length === 0 ? (

No secrets yet.

) : (
{secrets.map((s) => ( ))}
Owner Name Updated
{s.owner} {s.name} {formatTime(s.updated_at)}
)} {mode ? (
{mode === "add" ? "New secret" : `Replace ${form.owner}/${form.name}`}
{mode === "add" ? ( <> {owners.length > 0 ? ( ) : ( setForm({ ...form, owner: e.target.value })} required /> )} setForm({ ...form, name: e.target.value })} required pattern="[A-Za-z0-9._-]+" title="Letters, numbers, dots, underscores, hyphens" /> ) : null} setForm({ ...form, value: e.target.value })} required autoComplete="new-password" />

Values are encrypted at rest and never shown again after save. Values shorter than 8 characters are not redacted from logs.

{upsert.isError ? (

{errorMessage(upsert.error)}

) : null}
) : null} {confirmDelete ? (

Delete {confirmDelete.owner}/{confirmDelete.name}?

This cannot be undone. Workflows that retrieve this name will fail.

{del.isError ? (

{errorMessage(del.error)}

) : null}
) : null}
); }