mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
fix(ui): Overview denials metric card + Connections test fixture (PAP-10778)
Address QA findings from PAP-10789: - Overview 4th MetricCard is now "Denials (24h)" with a "N denied · M failed" sub-line (matching the v2 spec mockup), pairing with the denials table below, instead of the redundant Trust rules count. - Fix ConnectionsTab.test.tsx secret fixture to use valid SecretProvider / SecretManagedMode literals (local_encrypted / paperclip_managed); was failing tsc in the integrated tree. Typecheck (tsc -b) clean; Connections + transcript tests pass. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
452a72f180
commit
8bb16a93db
2 files changed
+18
-11
No files matched your search
@@ -100,9 +100,9 @@ function makeSecret(overrides: Partial<CompanySecret>): CompanySecret {
|
||||
companyId: "company-1",
|
||||
key: "github_token",
|
||||
name: "GitHub token",
|
||||
provider: "paperclip",
|
||||
provider: "local_encrypted",
|
||||
status: "active",
|
||||
managedMode: "managed",
|
||||
managedMode: "paperclip_managed",
|
||||
externalRef: null,
|
||||
providerConfigId: null,
|
||||
providerMetadata: null,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import type { ReactNode } from "react";
|
||||
import { Activity, AlertTriangle, AppWindow, Plug, Server, ShieldAlert, Shield } from "lucide-react";
|
||||
import { Activity, AlertTriangle, AppWindow, Plug, Server, ShieldAlert } from "lucide-react";
|
||||
import { Link } from "@/lib/router";
|
||||
import { queryKeys } from "@/lib/queryKeys";
|
||||
import { toolsApi } from "@/api/tools";
|
||||
@@ -75,7 +75,6 @@ export function OverviewTab({ companyId }: { companyId: string }) {
|
||||
const appList = apps.data?.applications ?? [];
|
||||
const connList = connections.data?.connections ?? [];
|
||||
const slotList = slots.data?.runtimeSlots ?? [];
|
||||
const trustList = trustRules.data?.trustRules ?? [];
|
||||
|
||||
const mcpApps = appList.filter((a) => a.type === "mcp_http" || a.type === "mcp_stdio").length;
|
||||
const pluginApps = appList.filter((a) => a.type === "paperclip_plugin").length;
|
||||
@@ -83,9 +82,17 @@ export function OverviewTab({ companyId }: { companyId: string }) {
|
||||
(c) => c.enabled && (c.status ?? "active") !== "archived",
|
||||
).length;
|
||||
const runningSlots = slotList.filter((s) => s.status === "running" || s.status === "idle").length;
|
||||
const enabledTrust = trustList.filter((t) => t.enabled).length;
|
||||
|
||||
const recentDenials = (audit.data ?? []).filter((row) => DENY_ACTIONS.has(row.action)).slice(0, 6);
|
||||
const allDenials = (audit.data ?? []).filter((row) => DENY_ACTIONS.has(row.action));
|
||||
const dayCutoff = Date.now() - 24 * 60 * 60 * 1000;
|
||||
const denials24h = allDenials.filter((row) => {
|
||||
const ts = new Date(row.createdAt).getTime();
|
||||
return !Number.isFinite(ts) || ts >= dayCutoff;
|
||||
});
|
||||
const deniedCount = denials24h.filter((row) => row.action.endsWith("denied")).length;
|
||||
const failedCount = denials24h.length - deniedCount;
|
||||
|
||||
const recentDenials = allDenials.slice(0, 6);
|
||||
const health = runtimeHealth.data;
|
||||
const metrics = health?.metrics;
|
||||
const firingAlerts = health?.alerts ?? [];
|
||||
@@ -126,11 +133,11 @@ export function OverviewTab({ companyId }: { companyId: string }) {
|
||||
</Card>
|
||||
<Card className="overflow-hidden py-0">
|
||||
<MetricCard
|
||||
icon={Shield}
|
||||
label="Trust rules"
|
||||
value={trustList.length}
|
||||
description={`${enabledTrust} enabled`}
|
||||
to="/company/settings/tools/policies"
|
||||
icon={ShieldAlert}
|
||||
label="Denials (24h)"
|
||||
value={denials24h.length}
|
||||
description={`${deniedCount} denied · ${failedCount} failed`}
|
||||
to="/company/settings/tools/audit"
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user