From d09422c5f37d97eb019b2fc6846f34f317b817d3 Mon Sep 17 00:00:00 2001 From: Christopher <131207452+PetrefiedThunder@users.noreply.github.com> Date: Fri, 23 Oct 2026 08:22:42 -0700 Subject: [PATCH 01/11] fix(dashboard): drop fabricated demo data from recall report page Remove the hardcoded demo investigation stats and affected-lot rows (invented suppliers, lot codes, consumer counts). Demo mode now renders the same No data yet empty state with a link to import records. --- .../__tests__/pages/recall-report.test.tsx | 24 ++- .../src/app/dashboard/recall-report/page.tsx | 194 ++---------------- 2 files changed, 32 insertions(+), 186 deletions(-) diff --git a/frontend/src/__tests__/pages/recall-report.test.tsx b/frontend/src/__tests__/pages/recall-report.test.tsx index f7db17565..5d2939e36 100644 --- a/frontend/src/__tests__/pages/recall-report.test.tsx +++ b/frontend/src/__tests__/pages/recall-report.test.tsx @@ -2,9 +2,9 @@ * Recall Report Page Tests * * Tests for the recall investigation / readiness report: - * - Renders heading and demo scenario + * - Renders heading * - Renders dimension scores - * - Falls back to demo data when API is unavailable + * - Shows the empty state instead of fabricated demo data in demo mode * - Auth guard (skips fetch without credentials) */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; @@ -45,7 +45,6 @@ const MOCK_DEMO_REPORT = { { priority: 'MEDIUM', action: 'Run mock recall drill', impact: 'Team readiness', effort: 'Low' }, ], demo_mode: true, - demo_disclaimer: 'Sample Scenario — Explore a realistic recall investigation.', }; // ── Mocks ── @@ -157,11 +156,14 @@ describe('RecallReportPage', () => { }); }); - it('renders demo investigation scenario data', async () => { + it('shows the empty state instead of fabricated demo data in demo mode', async () => { render(, { wrapper: createWrapper() }); await waitFor(() => { - expect(screen.getByText(/Romaine Lettuce/)).toBeInTheDocument(); + expect(screen.getByText('No data yet')).toBeInTheDocument(); }); + expect(screen.queryByText(/Romaine Lettuce/)).not.toBeInTheDocument(); + expect(screen.queryByText(/Salinas Valley Farms/)).not.toBeInTheDocument(); + expect(screen.queryByText(/SLA Met/)).not.toBeInTheDocument(); }); it('renders readiness dimension scores', async () => { @@ -174,20 +176,22 @@ describe('RecallReportPage', () => { expect(screen.getByText('Supplier Coverage')).toBeInTheDocument(); }); - it('renders affected lots table', async () => { + it('does not render fabricated affected lots', async () => { render(, { wrapper: createWrapper() }); await waitFor(() => { - expect(screen.getByText(/LOT-ROM-2026-0312A/)).toBeInTheDocument(); + expect(screen.getByText('No data yet')).toBeInTheDocument(); }); + expect(screen.queryByText(/LOT-ROM-2026/)).not.toBeInTheDocument(); }); - it('falls back to demo when API returns empty data', async () => { + it('shows the empty state with a next-step link in demo mode', async () => { mockFetchRecallReport.mockResolvedValue({ ...MOCK_DEMO_REPORT, demo_mode: true }); render(, { wrapper: createWrapper() }); - // Should still show the demo scenario since demo_mode is true await waitFor(() => { - expect(screen.getByText(/Romaine Lettuce/)).toBeInTheDocument(); + expect(screen.getByText('No data yet')).toBeInTheDocument(); }); + expect(screen.getByRole('link', { name: /import records/i })).toHaveAttribute('href', '/tools/data-import'); + expect(screen.queryByText(/Romaine Lettuce/)).not.toBeInTheDocument(); }); it('shows an error without fabricated results when the API fails', async () => { diff --git a/frontend/src/app/dashboard/recall-report/page.tsx b/frontend/src/app/dashboard/recall-report/page.tsx index 90d263c3f..a8f3f31c8 100644 --- a/frontend/src/app/dashboard/recall-report/page.tsx +++ b/frontend/src/app/dashboard/recall-report/page.tsx @@ -26,9 +26,7 @@ import { AlertTriangle, ArrowUp, Play, - MapPin, Clock, - CheckCircle2, Info, ChevronDown, ChevronUp, @@ -59,7 +57,6 @@ interface RecallReport { executive_summary: string; action_items: Array<{ priority: string; action: string; impact: string; effort: string }>; demo_mode: boolean; - demo_disclaimer?: string | null; } /* ── Icon + tone mappings ── */ @@ -85,28 +82,6 @@ const DIMENSION_ICONS: Record = { const NOTICE_BASE = 'flex gap-3 rounded-md border border-l-[3px] border-re-border px-4 py-3 text-ui text-re-text-secondary'; -/* ── Demo Fallback Data (shown only when demo_mode=true from API) ── */ - -const DEMO_INVESTIGATION = { - scenario: 'Romaine Lettuce (E. coli O157:H7)', - initiated: '2026-03-15T08:30:00Z', - response_time_hours: 4.2, - sla_target: 24, - lots_at_risk: 12, - suppliers_impacted: 3, - facilities_in_chain: 8, - consumers_potentially_affected: '~2,400', - total_quantity: '18,200 lbs', -}; - -const DEMO_AFFECTED_LOTS = [ - { tlc: 'LOT-ROM-2026-0312A', product: 'Organic Romaine Hearts', facility: 'Salinas Valley Farms', status: 'traced', cte_count: 6, last_event: 'Retail Distribution', risk: 'high' }, - { tlc: 'LOT-ROM-2026-0312B', product: 'Chopped Romaine Mix', facility: 'FreshCut Processing', status: 'traced', cte_count: 5, last_event: 'Transformation', risk: 'high' }, - { tlc: 'LOT-ROM-2026-0311C', product: 'Romaine Hearts 3-Pack', facility: 'Salinas Valley Farms', status: 'traced', cte_count: 4, last_event: 'Shipping', risk: 'medium' }, - { tlc: 'LOT-ROM-2026-0310D', product: 'Organic Romaine Bulk', facility: 'Pacific Coast Growers', status: 'partial', cte_count: 3, last_event: 'Receiving', risk: 'medium' }, - { tlc: 'LOT-ROM-2026-0309E', product: 'Romaine Salad Kit', facility: 'FreshCut Processing', status: 'partial', cte_count: 2, last_event: 'Transformation', risk: 'low' }, -]; - /* ── Helpers ── */ /** Grade as a badge tone. Numbers stay ink; only the grade pill carries colour. */ @@ -117,12 +92,6 @@ function gradeTone(grade: string): BadgeTone { return 'danger'; } -function riskTone(risk: string): BadgeTone { - if (risk === 'high') return 'danger'; - if (risk === 'medium') return 'warning'; - return 'success'; -} - function priorityTone(priority: string): BadgeTone { if (priority === 'HIGH') return 'danger'; if (priority === 'MEDIUM') return 'warning'; @@ -166,10 +135,6 @@ export default function RecallReportPage() { const overallGradeDisplay = overallGrade === '—' ? NO_DATA_YET : overallGrade; const responseTimeStr = report?.time_to_respond_estimate ?? NOT_SET; - // Demo-mode fallback stats for summary banner - const demoSlaPercent = Math.round((DEMO_INVESTIGATION.response_time_hours / DEMO_INVESTIGATION.sla_target) * 100); - const gaugeCircumference = 2 * Math.PI * 80; - const handleExport = async () => { if (!tenantId) return; setExporting(true); @@ -275,17 +240,6 @@ export default function RecallReportPage() { )} - {/* Demo notice */} - {isDemo && !isLoading && ( -
-
- )} - {/* Loading */} {isLoading && (
@@ -303,141 +257,29 @@ export default function RecallReportPage() { {!isLoading && ( <> - {/* ── DEMO ONLY: Risk Summary Banner ── */} - {isDemo && ( -
- {[ - { label: 'Lots at Risk', value: DEMO_INVESTIGATION.lots_at_risk }, - { label: 'Suppliers Impacted', value: DEMO_INVESTIGATION.suppliers_impacted }, - { label: 'Facilities in Chain', value: DEMO_INVESTIGATION.facilities_in_chain }, - { label: 'Consumers at Risk', value: DEMO_INVESTIGATION.consumers_potentially_affected }, - { label: 'Response Time', value: `${DEMO_INVESTIGATION.response_time_hours}h` }, - ].map((tile) => ( - -
{tile.label}
-
{tile.value}
-
- ))} -
- )} - - {/* ── DEMO ONLY: SLA Gauge + Timeline ── */} - {isDemo && ( -
- {/* SLA Gauge */} - - -
- 24-Hour Response Status -
-
- -
- -
-
{DEMO_INVESTIGATION.response_time_hours}h
-
of 24h SLA
-
-
- - -
-
- - {/* Investigation Timeline */} - - -
- Investigation Timeline - - {DEMO_INVESTIGATION.scenario} - -
-
- -

No recall timeline yet.

-

- Import records or run a trace to build the event timeline for an investigation. -

-
-
-
- )} - - {/* ── DEMO ONLY: Affected Lots ── */} - {isDemo && ( - - -
- Affected Lots ({DEMO_AFFECTED_LOTS.length}) -
- {DEMO_INVESTIGATION.total_quantity} total -
- -
    - {DEMO_AFFECTED_LOTS.map((lot) => ( -
  • -
    -
    {lot.tlc}
    -
    {lot.product}
    -
    -
    - - - {lot.cte_count} CTEs - - {lot.risk} - - - {lot.status === 'traced' ? ( - -
    -
  • - ))} -
-
-
- )} - - {/* ── LIVE ONLY: No Active Recall Empty State ── */} - {!isDemo && ( - + + + ) : ( - } - /> - )} + ) + } + /> {/* ── Readiness Score + Dimensions (always shown, live or demo) ── */}
From 81f3bfed301d6055cf633262cc4ca4d3fad48ab0 Mon Sep 17 00:00:00 2001 From: Christopher <131207452+PetrefiedThunder@users.noreply.github.com> Date: Fri, 23 Oct 2026 08:31:44 -0700 Subject: [PATCH 02/11] feat(copy): label every EPCIS intake and export mention as (Preview) EPCIS is preview on both paths, so feature-name mentions across app and marketing copy now carry the (Preview) marker. The integrations eyebrow now reads CSV upload, JSON events API, EPCIS (Preview). The FDA sortable export stays unlabeled. Stored keys and option values are unchanged. --- frontend/src/app/buyer-programs/page.tsx | 2 +- frontend/src/app/case-studies/page.tsx | 2 +- frontend/src/app/compliance/page.tsx | 2 +- frontend/src/app/dashboard/compliance/page.tsx | 4 ++-- frontend/src/app/dashboard/export-jobs/page.tsx | 6 +++--- frontend/src/app/dashboard/recall-drills/page.tsx | 2 +- frontend/src/app/developers/page.tsx | 2 +- frontend/src/app/docs/changelog/page.tsx | 2 +- frontend/src/app/fsma/integration/page.tsx | 2 +- frontend/src/app/ingest/page.tsx | 4 ++-- frontend/src/app/integrations/page.tsx | 2 +- frontend/src/app/proof/page.tsx | 10 +++++----- frontend/src/app/trust/architecture/page.tsx | 4 ++-- frontend/src/app/trust/page.tsx | 6 +++--- frontend/src/app/trust/retention/page.tsx | 4 ++-- frontend/src/app/walkthrough/page.tsx | 2 +- frontend/src/app/why-regengine/page.tsx | 12 ++++++------ frontend/src/lib/customer-readiness.ts | 12 ++++++------ 18 files changed, 40 insertions(+), 40 deletions(-) diff --git a/frontend/src/app/buyer-programs/page.tsx b/frontend/src/app/buyer-programs/page.tsx index 4c0b7c492..1ddbef30d 100644 --- a/frontend/src/app/buyer-programs/page.tsx +++ b/frontend/src/app/buyer-programs/page.tsx @@ -137,7 +137,7 @@ export default function BuyerProgramsPage() {
  • • Advisory coverage/completeness checklist
  • • Append-only commit
  • • FDA-oriented sortable spreadsheet
  • -
  • • CSV upload, JSON events API (EPCIS export)
  • +
  • • CSV upload, JSON events API, EPCIS export (Preview)
  • • Hash manifest re-checkable at /verify
  • diff --git a/frontend/src/app/case-studies/page.tsx b/frontend/src/app/case-studies/page.tsx index 324e1e589..0d4c7247b 100644 --- a/frontend/src/app/case-studies/page.tsx +++ b/frontend/src/app/case-studies/page.tsx @@ -453,7 +453,7 @@ export default function CaseStudy() { 'Date range filtering for targeted FDA requests', 'Chain verification JSON (SHA-256 + Merkle proof)', 'KDE completeness validation log', - 'EPCIS 2.0 JSON-LD (GS1 business step mapping)', + 'EPCIS 2.0 JSON-LD (Preview, GS1 business step mapping)', 'Package manifest with file checksums', ].map((item) => (
  • diff --git a/frontend/src/app/compliance/page.tsx b/frontend/src/app/compliance/page.tsx index 7dc5b5266..38177035e 100644 --- a/frontend/src/app/compliance/page.tsx +++ b/frontend/src/app/compliance/page.tsx @@ -257,7 +257,7 @@ export default function CompliancePage() {
    FSMA 204 - EPCIS 2.0 export + EPCIS 2.0 export (Preview) GS1 FDA CTEs KDEs diff --git a/frontend/src/app/dashboard/compliance/page.tsx b/frontend/src/app/dashboard/compliance/page.tsx index be965d0f8..ecc6744e6 100644 --- a/frontend/src/app/dashboard/compliance/page.tsx +++ b/frontend/src/app/dashboard/compliance/page.tsx @@ -141,7 +141,7 @@ const COMPLIANCE_SETUP_STEPS = [ }, { title: 'Preview export readiness', - detail: 'Once records exist, configure FDA and EPCIS export jobs for audit-response workflows.', + detail: 'Once records exist, configure FDA and EPCIS (Preview) export jobs for audit-response workflows.', href: '/dashboard/export-jobs', action: 'Set up exports', icon: Download, @@ -616,7 +616,7 @@ export default function ComplianceDashboardPage() { diff --git a/frontend/src/app/dashboard/export-jobs/page.tsx b/frontend/src/app/dashboard/export-jobs/page.tsx index d4a54ad8a..69d3cf415 100644 --- a/frontend/src/app/dashboard/export-jobs/page.tsx +++ b/frontend/src/app/dashboard/export-jobs/page.tsx @@ -182,7 +182,7 @@ export default function ExportJobsPage() { className={`${fieldControlClasses} h-11`} > - + @@ -250,7 +250,7 @@ export default function ExportJobsPage() {
    {exportPrereqs.map((step) => ( @@ -279,7 +279,7 @@ export default function ExportJobsPage() {
    {[ ['Cadence', 'Weekly / Daily / Monthly'], - ['Bundle', 'FDA or EPCIS'], + ['Bundle', 'FDA or EPCIS (Preview)'], ['Integrity', 'Manifest hash'], ].map(([term, detail]) => (
    diff --git a/frontend/src/app/dashboard/recall-drills/page.tsx b/frontend/src/app/dashboard/recall-drills/page.tsx index 113b62da5..2754c4a51 100644 --- a/frontend/src/app/dashboard/recall-drills/page.tsx +++ b/frontend/src/app/dashboard/recall-drills/page.tsx @@ -164,7 +164,7 @@ export default function RecallDrillsPage() { diff --git a/frontend/src/app/developers/page.tsx b/frontend/src/app/developers/page.tsx index e096f7a1c..352f94893 100644 --- a/frontend/src/app/developers/page.tsx +++ b/frontend/src/app/developers/page.tsx @@ -43,7 +43,7 @@ const capabilities = [ { Icon: FileSpreadsheet, title: 'Records Export', - description: 'Generate FDA-oriented sortable spreadsheet records and EPCIS 2.0 event exports where the enabled workflow and source data support them.', + description: 'Generate FDA-oriented sortable spreadsheet records and EPCIS 2.0 (Preview) event exports where the enabled workflow and source data support them.', }, { Icon: BarChart3, diff --git a/frontend/src/app/docs/changelog/page.tsx b/frontend/src/app/docs/changelog/page.tsx index c68568f6d..7143ad24d 100644 --- a/frontend/src/app/docs/changelog/page.tsx +++ b/frontend/src/app/docs/changelog/page.tsx @@ -83,7 +83,7 @@ export default function ChangelogPage() {

    Verification

      -
    • Offline verifier now validates the current audit bundle structure, including EPCIS package contents
    • +
    • Offline verifier now validates the current audit bundle structure, including EPCIS (Preview) package contents
    • Tampered proof-bundle sample added so evaluators can see failure detection instead of only the happy path
    • Root Docker deploy context and admin proxy routing aligned with the consolidated production surface
    diff --git a/frontend/src/app/fsma/integration/page.tsx b/frontend/src/app/fsma/integration/page.tsx index a3d3611c2..1476ae61e 100644 --- a/frontend/src/app/fsma/integration/page.tsx +++ b/frontend/src/app/fsma/integration/page.tsx @@ -69,7 +69,7 @@ export default function IntegrationHubPage() { {/* API / EPCIS */}