diff --git a/apps/web/package.json b/apps/web/package.json index a89e29b9a..2d4801cb0 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -51,9 +51,9 @@ "@kilocode/event-service": "workspace:*", "@kilocode/kilo-chat": "workspace:*", "@kilocode/kilo-chat-hooks": "workspace:*", - "@kilocode/mcp-gateway": "workspace:*", "@kilocode/kiloclaw-instance-tiers": "workspace:*", "@kilocode/kiloclaw-secret-catalog": "workspace:*", + "@kilocode/mcp-gateway": "workspace:*", "@kilocode/organization-entitlement": "workspace:*", "@kilocode/worker-utils": "workspace:*", "@linear/sdk": "76.0.0", @@ -151,6 +151,7 @@ "posthog-node": "5.10.4", "react": "19.2.6", "react-countup": "6.5.3", + "react-day-picker": "10.0.1", "react-dom": "19.2.6", "react-markdown": "10.1.0", "react-turnstile": "1.1.5", diff --git a/apps/web/src/app/(app)/organizations/[id]/security-agent/audit-report/page.tsx b/apps/web/src/app/(app)/organizations/[id]/security-agent/audit-report/page.tsx new file mode 100644 index 000000000..4384ebd19 --- /dev/null +++ b/apps/web/src/app/(app)/organizations/[id]/security-agent/audit-report/page.tsx @@ -0,0 +1,16 @@ +import { Suspense } from 'react'; +import { SecurityAuditReportPage } from '@/components/security-agent/SecurityAuditReportPage'; + +export default function OrgAuditReportPage() { + return ( + + Loading audit report... + + } + > + + + ); +} diff --git a/apps/web/src/app/(app)/organizations/[id]/security-agent/layout.tsx b/apps/web/src/app/(app)/organizations/[id]/security-agent/layout.tsx index 638507712..f068dd0d0 100644 --- a/apps/web/src/app/(app)/organizations/[id]/security-agent/layout.tsx +++ b/apps/web/src/app/(app)/organizations/[id]/security-agent/layout.tsx @@ -1,11 +1,10 @@ -import { PageContainer } from '@/components/layouts/PageContainer'; import { OrganizationByPageLayout } from '@/components/organizations/OrganizationByPageLayout'; import { SecurityAgentLayout } from '@/components/security-agent/SecurityAgentLayout'; import { SecurityAgentProvider } from '@/components/security-agent/SecurityAgentContext'; export const metadata = { title: 'Security Agent | Kilo Code', - description: 'Monitor and manage Dependabot security alerts', + description: 'Monitor and manage Security Findings synced from Dependabot', }; type LayoutProps = { @@ -17,12 +16,11 @@ export default async function OrgSecurityAgentLayout({ params, children }: Layou return ( ( - - - {children} - - + + {children} + )} /> ); diff --git a/apps/web/src/app/(app)/organizations/[id]/security-agent/page.tsx b/apps/web/src/app/(app)/organizations/[id]/security-agent/page.tsx index 537010dd3..ceb08de0f 100644 --- a/apps/web/src/app/(app)/organizations/[id]/security-agent/page.tsx +++ b/apps/web/src/app/(app)/organizations/[id]/security-agent/page.tsx @@ -1,32 +1,23 @@ 'use client'; -import { useRouter } from 'next/navigation'; -import { useEffect } from 'react'; +import { redirect } from 'next/navigation'; import { Loader2 } from 'lucide-react'; import { useSecurityAgent } from '@/components/security-agent/SecurityAgentContext'; import { SecurityDashboard } from '@/components/security-agent/SecurityDashboard'; export default function OrgSecurityAgentDashboardPage() { - const { hasIntegration, isEnabled, isLoadingConfig, organizationId } = useSecurityAgent(); - const router = useRouter(); + const { hasIntegration, isEnabled, isLoadingConfig, isLoadingPermission, organizationId } = + useSecurityAgent(); - const shouldRedirectToConfig = hasIntegration && isEnabled === false && !!organizationId; - - useEffect(() => { - if (shouldRedirectToConfig) { - router.replace(`/organizations/${organizationId}/security-agent/config`); - } - }, [shouldRedirectToConfig, organizationId, router]); + const shouldRedirectToConfig = + !!organizationId && + ((!isLoadingPermission && !hasIntegration) || (hasIntegration && isEnabled === false)); if (shouldRedirectToConfig) { - return ( -
- Opening settings... -
- ); + redirect(`/organizations/${organizationId}/security-agent/config`); } - if (hasIntegration && isLoadingConfig) { + if (isLoadingPermission || (hasIntegration && isLoadingConfig)) { return (
+ } + > + + + ); +} diff --git a/apps/web/src/app/(app)/security-agent/layout.tsx b/apps/web/src/app/(app)/security-agent/layout.tsx index 0ecdea21c..1e8336b45 100644 --- a/apps/web/src/app/(app)/security-agent/layout.tsx +++ b/apps/web/src/app/(app)/security-agent/layout.tsx @@ -1,18 +1,15 @@ -import { PageContainer } from '@/components/layouts/PageContainer'; import { SecurityAgentLayout } from '@/components/security-agent/SecurityAgentLayout'; import { SecurityAgentProvider } from '@/components/security-agent/SecurityAgentContext'; export const metadata = { title: 'Security Agent | Kilo Code', - description: 'Monitor and manage Dependabot security alerts', + description: 'Monitor and manage Security Findings synced from Dependabot', }; export default function SecurityAgentRootLayout({ children }: { children: React.ReactNode }) { return ( - - - {children} - - + + {children} + ); } diff --git a/apps/web/src/app/(app)/security-agent/page.tsx b/apps/web/src/app/(app)/security-agent/page.tsx index 3c5033dcf..2e38b07f4 100644 --- a/apps/web/src/app/(app)/security-agent/page.tsx +++ b/apps/web/src/app/(app)/security-agent/page.tsx @@ -1,37 +1,26 @@ 'use client'; -import { useRouter } from 'next/navigation'; -import { useEffect } from 'react'; +import { redirect } from 'next/navigation'; import { Loader2 } from 'lucide-react'; import { useSecurityAgent } from '@/components/security-agent/SecurityAgentContext'; import { SecurityDashboard } from '@/components/security-agent/SecurityDashboard'; export default function SecurityAgentDashboardPage() { - const { hasIntegration, isEnabled, isLoadingConfig } = useSecurityAgent(); - const router = useRouter(); + const { hasIntegration, isEnabled, isLoadingConfig, isLoadingPermission } = useSecurityAgent(); // Redirect per truth table: - // No integration -> show dashboard with install CTA (handled by SecurityDashboard) + // No integration -> redirect to settings with install CTA // Installed + disabled -> redirect to config // Installed + enabled -> show dashboard // isEnabled is undefined while config is loading — wait before deciding - const shouldRedirectToConfig = hasIntegration && isEnabled === false; - - useEffect(() => { - if (shouldRedirectToConfig) { - router.replace('/security-agent/config'); - } - }, [shouldRedirectToConfig, router]); + const shouldRedirectToConfig = + (!isLoadingPermission && !hasIntegration) || (hasIntegration && isEnabled === false); if (shouldRedirectToConfig) { - return ( -
- Opening settings... -
- ); + redirect('/security-agent/config'); } - if (hasIntegration && isLoadingConfig) { + if (isLoadingPermission || (hasIntegration && isLoadingConfig)) { return (