From b37cc0cb1e5522b06c810e2df409b79c4ecb57b1 Mon Sep 17 00:00:00 2001
From: Christopher <131207452+PetrefiedThunder@users.noreply.github.com>
Date: Fri, 23 Oct 2026 00:20:28 -0700
Subject: [PATCH 1/3] fix(frontend): keep manual drill and export routes in
unavailable views (SEL-411 follow-up)
---
.../__tests__/pages/dashboard-dead-ends.test.tsx | 14 ++++++++++++++
frontend/src/app/dashboard/export-jobs/page.tsx | 1 +
frontend/src/app/dashboard/recall-drills/page.tsx | 1 +
3 files changed, 16 insertions(+)
diff --git a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
index ecc2bf5ea..365835906 100644
--- a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
+++ b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
@@ -75,4 +75,18 @@ describe('disabled dashboard features', () => {
expect(screen.getByRole('button', { name: new RegExp(`${disabledAction} \\(coming soon\\)`, 'i') })).toBeDisabled();
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
});
+
+ it('keeps the manual Internal Drill path available', async () => {
+ renderPage( );
+
+ expect(await screen.findByRole('link', { name: 'Requests (Internal Drill)' })).toHaveAttribute('href', '/requests');
+ expect(screen.getByText(/create an Internal Drill case, and walk it scope → collect → gap analysis → assemble → submit/)).toBeInTheDocument();
+ });
+
+ it('keeps the on-demand tenant CSV export path available', async () => {
+ renderPage( );
+
+ expect(await screen.findByRole('link', { name: 'Recall Report' })).toHaveAttribute('href', '/dashboard/recall-report');
+ expect(screen.getByText(/on-demand tenant CSV export/)).toBeInTheDocument();
+ });
});
diff --git a/frontend/src/app/dashboard/export-jobs/page.tsx b/frontend/src/app/dashboard/export-jobs/page.tsx
index 253b5f43a..a660aceda 100644
--- a/frontend/src/app/dashboard/export-jobs/page.tsx
+++ b/frontend/src/app/dashboard/export-jobs/page.tsx
@@ -100,6 +100,7 @@ export default function ExportJobsPage() {
/>
Recurring archive scheduling is still in development. This workspace cannot create an export job here today.
+ For an on-demand tenant CSV export, open Recall Report.
To prepare traceability records now, use CSV upload or the JSON events API.
diff --git a/frontend/src/app/dashboard/recall-drills/page.tsx b/frontend/src/app/dashboard/recall-drills/page.tsx
index 6e6b5f16d..05ed37aa3 100644
--- a/frontend/src/app/dashboard/recall-drills/page.tsx
+++ b/frontend/src/app/dashboard/recall-drills/page.tsx
@@ -106,6 +106,7 @@ export default function RecallDrillsPage() {
Automated drill scheduling is still in development. This workspace cannot start a drill here today.
+
You can run a full manual drill today: open Requests (Internal Drill), create an Internal Drill case, and walk it scope → collect → gap analysis → assemble → submit.
To prepare traceability records now, use CSV upload or the JSON events API.
From e8ef2b4d5bb55fb052ae449cb8c537ac694297dd Mon Sep 17 00:00:00 2001
From: Christopher <131207452+PetrefiedThunder@users.noreply.github.com>
Date: Fri, 23 Oct 2026 00:58:05 -0700
Subject: [PATCH 2/3] test(SEL-411): data-free dead-end assertions
---
.../src/__tests__/pages/dashboard-dead-ends.test.tsx | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
index 365835906..35119679c 100644
--- a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
+++ b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
@@ -10,16 +10,16 @@ vi.mock('next/navigation', () => ({
}));
vi.mock('@/lib/auth-context', () => ({
- useAuth: () => ({ user: { id: 'user-1', is_sysadmin: false }, isHydrated: true, isAuthenticated: true }),
+ useAuth: () => ({ user: { is_sysadmin: false }, isHydrated: true, isAuthenticated: true }),
}));
vi.mock('@/lib/tenant-context', () => ({
- useTenant: () => ({ tenantId: 'tenant-1', isTenantReady: false }),
+ useTenant: () => ({ tenantId: null, isTenantReady: false }),
}));
vi.mock('@/hooks/use-api', () => ({
- useSystemStatus: () => ({ data: { overall_status: 'healthy', services: [] }, isLoading: false }),
- useSystemMetrics: () => ({ data: { open_alerts: 3, events_ingested: 1 }, isLoading: false }),
+ useSystemStatus: () => ({ data: null, isLoading: false }),
+ useSystemMetrics: () => ({ data: null, isLoading: false }),
}));
vi.mock('@/hooks/use-onboarding', () => ({
@@ -43,13 +43,12 @@ describe('disabled dashboard features', () => {
beforeEach(() => vi.stubEnv('NEXT_PUBLIC_ENABLE_EXPERIMENTAL_FEATURES', ''));
afterEach(() => vi.unstubAllEnvs());
- it('hides alerts and heartbeat links and replaces the alert count when the feature is off', () => {
+ it('hides alerts and heartbeat links and marks alerts off when the feature is off', () => {
renderPage( );
expect(linksTo('/dashboard/alerts')).toHaveLength(0);
expect(linksTo('/dashboard/heartbeat')).toHaveLength(0);
expect(screen.getByText('Alerts are off')).toBeInTheDocument();
- expect(screen.queryByText('3 open compliance alerts')).not.toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Recall drills (coming soon)' })).toHaveAttribute('href', '/dashboard/recall-drills');
});
@@ -60,7 +59,6 @@ describe('disabled dashboard features', () => {
expect(linksTo('/dashboard/alerts').length).toBeGreaterThan(0);
expect(linksTo('/dashboard/heartbeat')).toHaveLength(1);
expect(screen.queryByText('Alerts are off')).not.toBeInTheDocument();
- expect(screen.getByText('3 open compliance alerts')).toBeInTheDocument();
});
it.each([
From 6734ec846af4e6dad3dcda866f1f6d6ab74bbc92 Mon Sep 17 00:00:00 2001
From: Christopher <131207452+PetrefiedThunder@users.noreply.github.com>
Date: Fri, 23 Oct 2026 01:35:58 -0700
Subject: [PATCH 3/3] fix(SEL-411): drop Recall Report link from export-jobs
until #3471 removes recall-report demo data
---
frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx | 7 -------
frontend/src/app/dashboard/export-jobs/page.tsx | 1 -
2 files changed, 8 deletions(-)
diff --git a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
index 35119679c..c4224fd2e 100644
--- a/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
+++ b/frontend/src/__tests__/pages/dashboard-dead-ends.test.tsx
@@ -80,11 +80,4 @@ describe('disabled dashboard features', () => {
expect(await screen.findByRole('link', { name: 'Requests (Internal Drill)' })).toHaveAttribute('href', '/requests');
expect(screen.getByText(/create an Internal Drill case, and walk it scope → collect → gap analysis → assemble → submit/)).toBeInTheDocument();
});
-
- it('keeps the on-demand tenant CSV export path available', async () => {
- renderPage( );
-
- expect(await screen.findByRole('link', { name: 'Recall Report' })).toHaveAttribute('href', '/dashboard/recall-report');
- expect(screen.getByText(/on-demand tenant CSV export/)).toBeInTheDocument();
- });
});
diff --git a/frontend/src/app/dashboard/export-jobs/page.tsx b/frontend/src/app/dashboard/export-jobs/page.tsx
index a660aceda..253b5f43a 100644
--- a/frontend/src/app/dashboard/export-jobs/page.tsx
+++ b/frontend/src/app/dashboard/export-jobs/page.tsx
@@ -100,7 +100,6 @@ export default function ExportJobsPage() {
/>
Recurring archive scheduling is still in development. This workspace cannot create an export job here today.
- For an on-demand tenant CSV export, open Recall Report.
To prepare traceability records now, use CSV upload or the JSON events API.