# Horizon — Architecture ## Overview Next.js 15 App Router application. All pages are server or client components under `src/app/(dashboard)/`. Data access goes exclusively through Next.js API route handlers (`src/app/api/`), which use Prisma to talk to Postgres. ## Directory map ``` src/ ├── app/ │ ├── (dashboard)/ # Authenticated layout + all pages │ │ ├── layout.tsx # Shell: sidebar, nav, session guard │ │ ├── dashboard/ # Home/summary page │ │ ├── clients/ # Client list + detail ([id]/) │ │ ├── policies/ # Policy list + detail ([id]/) │ │ ├── tasks/ # Task list (page-client.tsx) + detail ([id]/) │ │ ├── admin/ # Admin-only pages (users, roles, designations, sync) │ │ └── manager/ # Manager pages (templates, metrics) │ ├── api/ # API route handlers │ │ ├── auth/ # NextAuth endpoints │ │ ├── clients/ # CRUD + notes, contacts, members │ │ ├── tasks/ # CRUD + notes, assignments │ │ ├── policies/ # CRUD + policy groups │ │ ├── policy-groups/ # Renewal group management │ │ ├── sync/ # Shape import sync │ │ ├── users/ # User management │ │ ├── roles/ # Role management │ │ ├── templates/ # Task templates │ │ ├── designations/ # Client designations │ │ ├── metrics/ # Dashboard metrics │ │ ├── cron/ # Scheduled jobs (notifications, etc.) │ │ └── dashboard/ # Dashboard summary data │ ├── auth/ # Sign-in / error pages (unauthenticated) │ └── layout.tsx # Root layout (providers, theme) ├── components/ │ ├── ui/ # shadcn/ui primitives (Button, Dialog, Input, etc.) │ ├── clients/ # Client-specific components │ ├── tasks/ # Task card, task edit modal │ ├── policies/ # Policy components │ ├── renewal-groups/ # Policy group components │ ├── notifications/ # Notification bell + panel │ ├── admin/ # Admin UI components │ ├── manager/ # Manager UI components │ ├── layout/ # Sidebar, header, nav │ └── providers/ # SessionProvider, ThemeProvider ├── lib/ │ ├── auth.ts # NextAuth config (Entra ID + local credentials) │ ├── db.ts # Prisma client singleton │ ├── entra.ts # Microsoft Graph API helpers │ ├── utils.ts # Shared utilities (cn(), formatters) │ ├── hooks/ # Custom React hooks │ ├── sync/ # Shape import sync logic │ ├── shape-import/ # Shape file parsing │ └── tasks/ # Task business logic helpers ├── middleware.ts # Auth middleware (protects all dashboard routes) └── types/ # Shared TypeScript types ``` ## Data models (key entities) | Model | Description | |-------|-------------| | `User` | Staff accounts; synced from Entra ID | | `Role` / `UserRole` | RBAC roles (Admin, Manager, AE, Claims, etc.) | | `Client` | Insurance clients; synced from AMS via Shape import | | `ClientContact` | Contacts per client | | `ClientMember` | Which staff are assigned to a client | | `Designation` | Client classification labels (color-coded) | | `Policy` | Insurance policies linked to clients | | `PolicyGroup` | Renewal groups grouping policies | | `Task` | Work items linked to client/policy/policy group | | `TaskAssignment` | Which users are assigned to a task | | `TaskNote` | Notes on tasks with status snapshots | | `TaskTemplate` | Reusable task templates for automation | | `SyncLog` | History of Shape import runs | | `AuditLog` | Field-level change tracking | | `Notification` | In-app notifications per user | | `ShapeImportRun` | Shape file import run tracking | ## Auth flow 1. `middleware.ts` checks NextAuth session on every request under `/(dashboard)`. 2. Unauthenticated users are redirected to `/auth/signin`. 3. Production: Microsoft Entra ID OAuth. Entra group memberships map to Horizon roles via `EntraGroupRoleMapping`. 4. Dev: local credentials provider (see `src/lib/auth.ts`). ## Task completion flow - UI: `src/app/(dashboard)/tasks/page-client.tsx` (task detail page) and `src/components/tasks/task-card.tsx` (list card) - Dialog collects: completion date, ImageRight filing confirmation, optional reminder date - `PATCH /api/tasks/[id]` sets `completedAt`, `completedBy`, `imageRightFiled`, `reminderDate` ## Sync / data import - Client and policy data synced from Zywave/Applied AMS via Shape file import - Shape import logic: `src/lib/shape-import/` and `src/lib/sync/` - Triggered manually from Admin UI or via scheduled cron (`src/app/api/cron/`) - Sync history tracked in `SyncLog` and `AuditLog` ## Deployment - Production: Docker Compose at `/opt/stacks/horizon` - Image built from this directory's `Dockerfile` (Next.js standalone output) - DB: Postgres 17 in `horizon-db` container - Reverse proxy: Pangolin → https://horizon.seubert.cloud