feat(diagnostics): correlate staff operations errors and audit records
CI / check (push) Successful in 56s
CI / deploy (push) Successful in 19s
CI / publish-container (push) Successful in 1m15s

This commit is contained in:
Simo committed 2026-09-11 00:34:49 +02:00
1 parent 440ce4e556
commit a2954e4408
14 files changed
+473 -110

No files matched your search

+11 -6
View File
@@ -167,8 +167,8 @@ export default async function CmsErrorsPage({
<details key={fingerprint} className="admin-card overflow-hidden">
<summary className="cursor-pointer">
<span className="text-xs text-muted-foreground">
{t(r.resolved ? "resolved" : "open")} · {r.source} ·{" "}
{t("occurrences", { count: events.length })} · {r.at}
{t(r.resolved ? "resolved" : "open")} · {r.source} ·{" "}
{t("occurrences", { count: events.length })} · {r.at}
</span>
<p className="font-semibold break-words">{r.event}</p>
<p className="text-sm break-words">{r.message}</p>
@@ -248,6 +248,11 @@ export default async function CmsErrorsPage({
)}
</form>
)}
{metrics.auditLink && (
<Link href={metrics.auditLink} className="btn btn-outline">
{t("auditTrail")}
</Link>
)}
{metrics.operationLink && (
<Link
href={metrics.operationLink}
@@ -263,9 +268,9 @@ export default async function CmsErrorsPage({
<ul className="mt-2 space-y-2">
{metrics.releases.map((release) => (
<li key={release.release} className="break-all">
<code>{release.release}</code> ·{" "}
{t("occurrences", { count: release.count })} ·{" "}
{release.firstAt} — {release.lastAt}
<code>{release.release}</code> ·{" "}
{t("occurrences", { count: release.count })} ·{" "}
{release.firstAt} — {release.lastAt}
</li>
))}
</ul>
@@ -308,7 +313,7 @@ export default async function CmsErrorsPage({
<ul>
{events.map((e) => (
<li key={e.id} className="break-all">
{e.at} · {e.id}
{e.at} · {e.id}
</li>
))}
</ul>
+10
View File
@@ -1,5 +1,6 @@
"use client";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useTranslations } from "next-intl";
import { DataTable } from "@/components/admin/data-table";
@@ -10,6 +11,7 @@ import type { DataTableColumn, PaginatedResult } from "@/types/common";
import { AuditFilters } from "./audit-filters";
interface AuditRow {
operationId?: string | null;
id: number;
username: string;
action: string;
@@ -106,6 +108,14 @@ export function AuditTable({ data }: AuditTableProps) {
render: (_value, row) => (
<div className="space-y-2">
<DiffCell row={row} />
{row.operationId && (
<Link
className="text-xs underline break-all"
href={`/admin/devops/cms-errors?q=${encodeURIComponent(row.operationId)}`}
>
{t("audit.operation")}: {row.operationId}
</Link>
)}
{["history_update", "history_restore"].includes(row.action) && (
<HistoryRestore id={row.id} />
)}