diff --git a/.planning/phases/04-frontend/04-RESEARCH.md b/.planning/phases/04-frontend/04-RESEARCH.md
new file mode 100644
index 0000000..5c407bc
--- /dev/null
+++ b/.planning/phases/04-frontend/04-RESEARCH.md
@@ -0,0 +1,511 @@
+# Phase 4: Frontend - Research
+
+**Researched:** 2026-02-24
+**Domain:** React + TypeScript frontend integration with admin monitoring APIs
+**Confidence:** HIGH
+
+## Summary
+
+Phase 4 wires the existing React/TypeScript/Tailwind frontend to the three admin API endpoints delivered in Phase 3: `GET /admin/health`, `GET /admin/analytics`, and `GET /admin/alerts` + `POST /admin/alerts/:id/acknowledge`. The frontend already has a complete admin-detection pattern, tab-based navigation, an axios-backed `adminService.ts`, and a `ProtectedRoute` component. The work is pure frontend integration — no new infrastructure, no new libraries, no new backend routes.
+
+The stack is locked: React 18 + TypeScript + Tailwind CSS + lucide-react icons + react-router-dom v6 + axios (via `adminService.ts`). The project uses `clsx` and `tailwind-merge` (via `cn()`) for conditional class composition. No charting library is installed. The existing `Analytics.tsx` component shows the styling and layout patterns to follow. The existing `UploadMonitoringDashboard.tsx` shows the health indicator pattern with colored circles.
+
+The primary implementation risk is the alert acknowledgement UX: after calling `POST /admin/alerts/:id/acknowledge`, the local state must update immediately (optimistic update or re-fetch) so the banner disappears without waiting for a full page refresh. The alert banner must render above the tab navigation because it is a global signal, not scoped to a specific tab.
+
+**Primary recommendation:** Add new components to the existing `monitoring` tab in App.tsx, extend `adminService.ts` with the three monitoring API methods, add an `AdminMonitoringDashboard` component, add an `AlertBanner` component that renders above the nav inside `Dashboard`, and add an `AdminRoute` wrapper that shows access-denied for non-admins who somehow hit the monitoring tab directly.
+
+---
+
+
+## Phase Requirements
+
+| ID | Description | Research Support |
+|----|-------------|-----------------|
+| ALRT-03 | Admin sees in-app alert banner for active critical issues; banner disappears after acknowledgement | alertBanner component using GET /admin/alerts + POST /admin/alerts/:id/acknowledge; optimistic state update on acknowledge |
+| ANLY-02 (UI) | Admin dashboard shows processing summary: upload counts, success/failure rates, avg processing time | AdminMonitoringDashboard section consuming GET /admin/analytics response shape (AnalyticsSummary interface) |
+| HLTH-01 (UI) | Admin dashboard shows health status indicators (green/yellow/red) for all four services with last-checked timestamp | ServiceHealthPanel component consuming GET /admin/health; status → color mapping green=healthy, yellow=degraded, red=down/unknown |
+
+*Note: ANLY-02 and HLTH-01 were marked Complete in Phase 3 (backend side). Phase 4 completes their UI delivery.*
+
+
+---
+
+## Standard Stack
+
+### Core (already installed — no new packages needed)
+
+| Library | Version | Purpose | Why Standard |
+|---------|---------|---------|--------------|
+| react | ^18.2.0 | Component rendering | Project standard |
+| typescript | ^5.2.2 | Type safety | Project standard |
+| tailwindcss | ^3.3.5 | Utility CSS | Project standard |
+| lucide-react | ^0.294.0 | Icons (AlertTriangle, CheckCircle, Activity, Clock, etc.) | Already used throughout |
+| axios | ^1.6.2 | HTTP client (via adminService) | Already used in adminService.ts |
+| clsx + tailwind-merge | ^2.0.0 / ^2.0.0 | Conditional class composition via `cn()` | Already used in Analytics.tsx |
+| react-router-dom | ^6.20.1 | Routing, Navigate | Already used |
+
+### No New Libraries Required
+
+All required UI capabilities exist in the current stack:
+- Status indicators: plain `div` with Tailwind bg-green-500 / bg-yellow-500 / bg-red-500
+- Alert banner: fixed/sticky div above nav, standard Tailwind layout
+- Timestamps: `new Date(ts).toLocaleString()` or `toRelative()` — no date library needed
+- Loading state: existing spinner pattern (`animate-spin rounded-full border-b-2`)
+
+**Installation:** None required.
+
+---
+
+## Architecture Patterns
+
+### Recommended File Changes
+
+```
+frontend/src/
+├── components/
+│ ├── AlertBanner.tsx # NEW — global alert banner above nav
+│ ├── AdminMonitoringDashboard.tsx # NEW — health + analytics panel
+│ └── (existing files unchanged)
+├── services/
+│ └── adminService.ts # EXTEND — add getHealth(), getAnalytics(), getAlerts(), acknowledgeAlert()
+└── App.tsx # MODIFY — render AlertBanner, wire monitoring tab to new component
+```
+
+### Pattern 1: Alert Banner — global, above nav, conditional render
+
+**What:** A dismissible/acknowledgeable banner rendered inside `Dashboard` ABOVE the `