fix: sanitize traffic monitor auth surface
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s

This commit is contained in:
OG T
2026-06-11 19:37:28 +08:00
parent 2fd0570295
commit e11e70ab19
2 changed files with 52 additions and 9 deletions

View File

@@ -99,6 +99,32 @@ function explainAction(action: string) {
return EVENT_LABELS[action] || action;
}
function displayEntityId(value: string | null | undefined) {
if (!value || value === "-") return "-";
const normalized = value.toLowerCase();
if (normalized.includes("growth-kit")) return "成長導流素材";
if (normalized.includes("demand-campaign")) return "需求導流素材";
if (normalized.includes("onboarding")) return "合作說明";
if (normalized.includes("integration")) return "整合目錄";
if (normalized.includes("referral-status")) return "引薦狀態";
if (normalized.includes("proposal-intake")) return "提案入口";
if (value.length > 42) return `${value.slice(0, 18)}...${value.slice(-8)}`;
return value;
}
function displayResponseSummary(value: string | null | undefined) {
if (!value || value === "unknown") return "n/a";
const normalized = value.toLowerCase();
if (normalized.includes("growth_kit")) return "已發出成長導流素材";
if (normalized.includes("demand_campaign")) return "已發出需求導流素材";
if (normalized.includes("referral_status")) return "已回傳引薦狀態";
if (normalized.includes("onboarding")) return "已回傳合作說明";
if (normalized.includes("integrations")) return "已回傳整合目錄";
if (normalized.includes("proposal_view")) return "已記錄提案頁查看";
if (normalized.includes("proposal")) return "已記錄提案流程";
return value.replace(/_/g, " ");
}
type TrafficActorClass = "a2a" | "external_ai_agent" | "likely_ai_agent" | "other_external";
const AI_USER_AGENT_HINTS = [
@@ -925,7 +951,7 @@ export default async function TrafficDashboard({
</div>
<div className="bg-gray-900 border border-gray-800 rounded-2xl p-6">
<h2 className="text-xl font-semibold mb-4"> Actor 20</h2>
<h2 className="text-xl font-semibold mb-4"> 20</h2>
<div className="space-y-2 max-h-80 overflow-auto">
{summary.externalActorSummary.length === 0 ? (
<p className="text-gray-500"> Actor</p>
@@ -941,7 +967,7 @@ export default async function TrafficDashboard({
</div>
<div className="bg-gray-900 border border-gray-800 rounded-2xl p-6">
<h2 className="text-xl font-semibold mb-4">Actor </h2>
<h2 className="text-xl font-semibold mb-4"></h2>
<div className="space-y-2">
{Object.entries(summary.actorSummary).map(([actorType, count]) => (
<div key={actorType} className="flex justify-between text-sm">
@@ -989,13 +1015,13 @@ export default async function TrafficDashboard({
<td className="py-2">
<div className="text-gray-200">{explainAction(actor.latestAction)}</div>
</td>
<td className="py-2 text-gray-300">{actor.latestTaskId}</td>
<td className="py-2 text-gray-300">{displayEntityId(actor.latestTaskId)}</td>
<td className="py-2 text-gray-300">{actor.latestSourceIp}</td>
<td className="py-2 text-gray-300">{actor.latestUserAgent}</td>
<td className="py-2 text-gray-300">{actor.latestRequestId}</td>
<td className="py-2">
<div className="text-gray-200">{actor.latestResponseStatus ?? "n/a"}</div>
<div className="text-xs text-gray-500">{actor.latestResponseSummary}</div>
<div className="text-xs text-gray-500">{displayResponseSummary(actor.latestResponseSummary)}</div>
</td>
</tr>
))
@@ -1012,8 +1038,8 @@ export default async function TrafficDashboard({
.filter(([action]) => action.startsWith("EXTERNAL_"))
.sort((a, b) => b[1] - a[1])
.slice(0, 14)
.map(([action, count]) => (
<div key={action} className="flex justify-between border-b border-gray-800 py-1">
.map(([action, count], index) => (
<div key={`external-summary-${index}`} className="flex justify-between border-b border-gray-800 py-1">
<span className="text-gray-300">{explainAction(action)}</span>
<span className="text-emerald-300">{count}</span>
</div>
@@ -1047,10 +1073,10 @@ export default async function TrafficDashboard({
<div key={event.id} className="border-b border-gray-800 py-2 text-sm">
<div className="text-emerald-300">{explainAction(event.action)}</div>
<div className="text-gray-400">
{event.actorId || "unknown"}{actorClassLabel((event as { actor_class?: TrafficActorClass }).actor_class || "other_external")}{event.entityId || "-"}{ts}
{event.actorId || "unknown"}{actorClassLabel((event as { actor_class?: TrafficActorClass }).actor_class || "other_external")}{displayEntityId(event.entityId)}{ts}
</div>
<div className="text-gray-500 text-xs mt-1">
{event.response_status ?? "n/a"} / {event.response_summary}
{event.response_status ?? "n/a"} / {displayResponseSummary(event.response_summary)}
</div>
</div>
);