@skyhook-io/radar-app 1.9.5 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -10
- package/src/api/client.authRedirect.test.ts +194 -0
- package/src/api/client.trace.test.ts +37 -0
- package/src/api/client.ts +136 -3
- package/src/api/diagnose.ts +12 -0
- package/src/components/CloudConnectFlow.tsx +7 -7
- package/src/components/CloudFunnelButton.tsx +87 -64
- package/src/components/diagnose/DiagnoseContext.tsx +38 -6
- package/src/components/diagnose/DiagnoseSurface.test.tsx +70 -0
- package/src/components/diagnose/DiagnoseSurface.tsx +50 -0
- package/src/components/diagnose/InvestigationView.tsx +44 -7
- package/src/components/diagnose/parts.test.tsx +39 -0
- package/src/components/diagnose/parts.tsx +22 -1
- package/src/components/home/HomeView.tsx +6 -1
- package/src/components/home/mcpToolCatalog.ts +7 -5
- package/src/components/workload/WorkloadView.tsx +580 -16
|
@@ -649,11 +649,17 @@ function ConsentCardShell({
|
|
|
649
649
|
settingsLabel,
|
|
650
650
|
approveLabel = "Approve & investigate",
|
|
651
651
|
warning = false,
|
|
652
|
+
error,
|
|
652
653
|
onOpenSettings,
|
|
653
654
|
onApprove,
|
|
654
655
|
onCancel,
|
|
655
656
|
}: DiagnoseConsentCopy & {
|
|
656
657
|
warning?: boolean;
|
|
658
|
+
// Why the last approval failed, straight from the server. The card stays up on
|
|
659
|
+
// failure so retrying works in place, which means this is the ONLY chance to
|
|
660
|
+
// say why — a host that records consent above the individual refuses the
|
|
661
|
+
// wrong person here, and only its message knows who to ask.
|
|
662
|
+
error?: string | null;
|
|
657
663
|
onOpenSettings?: () => void;
|
|
658
664
|
onApprove: () => void;
|
|
659
665
|
onCancel: () => void;
|
|
@@ -698,6 +704,19 @@ function ConsentCardShell({
|
|
|
698
704
|
{resolvedSettingsLabel}
|
|
699
705
|
</button>
|
|
700
706
|
)}
|
|
707
|
+
{/* Red, not amber: the full-local card is itself amber, so an amber box on
|
|
708
|
+
it reads as another paragraph of body copy. role="alert" because nothing
|
|
709
|
+
else moves on failure — focus stays on Approve, so without it a screen
|
|
710
|
+
reader says nothing and the user re-presses a button that cannot succeed. */}
|
|
711
|
+
{error && (
|
|
712
|
+
<div
|
|
713
|
+
role="alert"
|
|
714
|
+
className="mt-3 flex items-start gap-2 rounded-md border border-red-500/30 bg-red-500/10 p-2 text-xs text-theme-text-primary"
|
|
715
|
+
>
|
|
716
|
+
<AlertTriangle className="mt-0.5 h-3.5 w-3.5 shrink-0 text-red-400" />
|
|
717
|
+
<span>{error}</span>
|
|
718
|
+
</div>
|
|
719
|
+
)}
|
|
701
720
|
<div className="mt-4 flex gap-2">
|
|
702
721
|
<button
|
|
703
722
|
onClick={onCancel}
|
|
@@ -731,6 +750,7 @@ export function ConsentCard({
|
|
|
731
750
|
agent,
|
|
732
751
|
profile,
|
|
733
752
|
copy,
|
|
753
|
+
error,
|
|
734
754
|
onOpenSettings,
|
|
735
755
|
onApprove,
|
|
736
756
|
onCancel,
|
|
@@ -739,11 +759,12 @@ export function ConsentCard({
|
|
|
739
759
|
agent?: string;
|
|
740
760
|
profile: ExecutionProfile;
|
|
741
761
|
copy?: DiagnoseConsentCopy;
|
|
762
|
+
error?: string | null;
|
|
742
763
|
onOpenSettings?: () => void;
|
|
743
764
|
onApprove: () => void;
|
|
744
765
|
onCancel: () => void;
|
|
745
766
|
}) {
|
|
746
|
-
const chrome = { onOpenSettings, onApprove, onCancel };
|
|
767
|
+
const chrome = { onOpenSettings, onApprove, onCancel, error };
|
|
747
768
|
|
|
748
769
|
// Tier 1: a host (e.g. radar-hub-web) supplied its own copy — use it verbatim.
|
|
749
770
|
if (copy) return <ConsentCardShell {...copy} {...chrome} />;
|
|
@@ -390,9 +390,14 @@ function ProblemsPanel({
|
|
|
390
390
|
<div className="flex items-center gap-1.5">
|
|
391
391
|
<span className="text-[10px] text-theme-text-tertiary bg-theme-elevated px-1 py-0.5 rounded">{issue.kind}</span>
|
|
392
392
|
<span className="text-xs text-theme-text-primary truncate font-medium">{issue.name}</span>
|
|
393
|
-
{(age || timing) && (
|
|
393
|
+
{(age || timing || issue.onset_unknown) && (
|
|
394
394
|
<span className="ml-auto flex shrink-0 items-center gap-1">
|
|
395
395
|
{age && <span className="text-[10px] text-theme-text-tertiary tabular-nums">{age}</span>}
|
|
396
|
+
{issue.onset_unknown && (
|
|
397
|
+
<Tooltip content="Radar can confirm this issue is active, but current Kubernetes state does not reveal when it began." delay={100}>
|
|
398
|
+
<span className="text-[10px] text-theme-text-tertiary">Onset unknown</span>
|
|
399
|
+
</Tooltip>
|
|
400
|
+
)}
|
|
396
401
|
{timing && (
|
|
397
402
|
<Tooltip content={timing.tooltip} delay={100}>
|
|
398
403
|
<span className="badge-sm text-[10px] text-theme-text-secondary">{timing.chip}</span>
|
|
@@ -109,14 +109,16 @@ export const MCP_TOOL_CATALOG: MCPToolInfo[] = [
|
|
|
109
109
|
},
|
|
110
110
|
{
|
|
111
111
|
name: 'diagnose',
|
|
112
|
-
desc: 'One-call root-cause bundle. Workloads get spec + resourceContext + current AND previous logs across pods + warning events + startup blockers; GitOps reconcilers, including Flux HelmRelease, get status summary + parsed related issues.',
|
|
112
|
+
desc: 'One-call root-cause bundle. Workloads get spec + resourceContext + current AND previous logs across pods + warning events + startup blockers; GitOps reconcilers, including Flux HelmRelease, get status summary + parsed related issues; network entry kinds (Service / Ingress / HTTPRoute / GRPCRoute / Gateway) get a path-shaped trace naming the first broken hop, with an optional one-shot reachability test.',
|
|
113
113
|
params: [
|
|
114
|
-
{ arg: 'kind', required: true, desc: 'pod, deployment, statefulset, daemonset, application, kustomization,
|
|
114
|
+
{ arg: 'kind', required: true, desc: 'pod, deployment, statefulset, daemonset, application, kustomization, Flux HelmRelease, service, ingress, httproute, grpcroute, or gateway' },
|
|
115
115
|
{ arg: 'namespace', required: true, desc: 'resource namespace' },
|
|
116
116
|
{ arg: 'name', required: true, desc: 'resource name' },
|
|
117
|
-
{ arg: '
|
|
118
|
-
{ arg: '
|
|
119
|
-
{ arg: '
|
|
117
|
+
{ arg: 'probe', desc: 'network kinds only: add active DNS/TCP/TLS/HTTP probes against the declared path (0-3s wall time)' },
|
|
118
|
+
{ arg: 'in_cluster', desc: 'network kinds: run the probe from inside the cluster via short-lived self-destructing pods (real dataplane) - confirms a route the apiserver proxy could only reach indirectly. Creates up to 5 short-lived probe pods (one per dialed target) under your RBAC' },
|
|
119
|
+
{ arg: 'container', desc: 'workload kinds: specific container (defaults to all)' },
|
|
120
|
+
{ arg: 'tail_lines', desc: 'workload kinds: lines per pod/stream (default 100)' },
|
|
121
|
+
{ arg: 'since', desc: 'workload kinds: only logs newer than this duration' },
|
|
120
122
|
],
|
|
121
123
|
},
|
|
122
124
|
{
|