import Link from 'next/link' import { notFound, redirect } from 'next/navigation' import { getCurrentUser } from '@/lib/session' import { prisma } from '@/lib/prisma' export const dynamic = 'force-dynamic' type Props = { params: Promise<{ flow_run_id: string }> } const STATUS_STYLES: Record = { pending: 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400', running: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400', success: 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400', failed: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400', cancelled: 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400', } export default async function AuditDetailPage({ params }: Props) { const user = await getCurrentUser() if (!user) redirect('/login') const { flow_run_id } = await params const run = await prisma.flowRun.findUnique({ where: { id: flow_run_id }, include: { steps: { orderBy: { step_index: 'asc' } } }, }) if (!run || run.user_id !== user.id) notFound() const durationMs = run.ended_at && run.started_at ? run.ended_at.getTime() - run.started_at.getTime() : null return (
← Audit Log /

{run.flow_key}

Status
{run.status}
Exit code
{run.exit_code != null ? run.exit_code : '—'}
Started
{run.started_at.toLocaleString()}
Duration
{durationMs != null ? `${(durationMs / 1000).toFixed(1)}s` : '—'}
{run.steps.map((step) => { const args = step.args_json ? (JSON.parse(step.args_json) as string[]) : [] return (
Step {step.step_index + 1} {step.command_key} {args.length > 0 && ( {args.join(' ')} )}
{(step.stdout || step.stderr) && (
{step.stdout && (
                        {step.stdout}
                      
)} {step.stderr && (
                        {step.stderr}
                      
)}
exit {step.exit_code != null ? step.exit_code : '—'} {step.ended_at && step.started_at && ( {((step.ended_at.getTime() - step.started_at.getTime()) / 1000).toFixed(1)}s )}
)} {!step.stdout && !step.stderr && (
No output recorded.
)}
) })}
) }