# Tasks: Auvik Integration ## Relevant Files - `/lib/types/auvik.ts` - TypeScript type definitions for Auvik API entities (devices, tenants, interfaces) - `/lib/services/auvik-client.ts` - Auvik API client service for making authenticated requests - `/lib/services/auvik-factory.ts` - Singleton factory pattern for Auvik client instantiation - `/app/api/auvik/devices/route.ts` - API endpoint for fetching Auvik devices with tenant filtering - `/components/configuration-items/auvik-tab.tsx` - React component for displaying Auvik device details in modal - `/components/configuration-items/config-item-modal.tsx` - Existing modal component (modify to add Auvik tab) - `/app/configuration-items/page.tsx` - Main configuration items page (modify to add Auvik column) - `/app/api/configuration-items/[id]/route.ts` - Existing API route (modify to include Auvik device matching) - `/app/api/rmm-devices/route.ts` - Existing comparison endpoint (modify to include Auvik matching) ### Notes - Follow existing patterns from Datto RMM integration (`datto-rmm-client.ts`, `rmm-tab.tsx`) - Use Basic Authentication for Auvik API (username:password in Authorization header) - Auvik API documentation: https://support.auvik.com/hc/en-us/articles/360031007111 - Test with real Auvik credentials from `.env` file - Ensure graceful degradation when Auvik API is unavailable ## Tasks - [ ] 1.0 Create Auvik TypeScript Types and API Client - [ ] 1.1 Create `/lib/types/auvik.ts` with TypeScript interfaces for AuvikDevice, AuvikTenant, AuvikNetworkInterface, and API response structures - [ ] 1.2 Define AuvikDevice interface with fields: id, deviceName, serialNumber, macAddresses, ipAddresses, deviceType, manufacturer, model, firmwareVersion, onlineStatus, lastSeenTime, uptime, tenantId, tenantName - [ ] 1.3 Define AuvikNetworkInterface interface with fields: interfaceName, status, speed, macAddress, ipAddress, vlan - [ ] 1.4 Create `/lib/services/auvik-client.ts` implementing AuvikClient class with constructor accepting config (apiUrl, apiUser, apiKey) - [ ] 1.5 Implement `getAuthHeaders()` method that returns Basic Authentication header (Base64 encoded username:password) - [ ] 1.6 Implement `makeApiCall()` method for generic API requests with error handling and logging - [ ] 1.7 Implement `getAllDevices()` method to fetch device inventory from `/v1/inventory/device/info` endpoint - [ ] 1.8 Implement `getDevicesByTenant(tenantId: string)` method with tenant filtering - [ ] 1.9 Implement `getTenants()` method to fetch tenant list from `/v1/tenants` endpoint - [ ] 1.10 Add rate limiting logic to respect Auvik API limits (track request count and timestamps) - [ ] 1.11 Create `/lib/services/auvik-factory.ts` with `getAuvikClient()` singleton factory function - [ ] 1.12 Load Auvik credentials from environment variables in factory (AUVIK_API_URL, AUVIK_API_USER, AUVIK_API_KEY) - [ ] 2.0 Implement Auvik API Endpoints - [ ] 2.1 Create `/app/api/auvik/devices/route.ts` with GET handler - [ ] 2.2 Accept query parameters: `companyId` (optional), `companyName` (optional) - [ ] 2.3 If companyName provided, fetch Auvik tenants and find matching tenant by name (case-insensitive, fuzzy match) - [ ] 2.4 If tenant match found, fetch devices filtered by tenantId; otherwise fetch all devices - [ ] 2.5 Transform Auvik API response to match AuvikDevice interface structure - [ ] 2.6 Implement try-catch error handling that logs errors but returns 200 with empty array on failure - [ ] 2.7 Add console logging for tenant matching results and device counts - [ ] 2.8 Return JSON response with devices array and optional metadata (tenantId, tenantName) - [ ] 3.0 Add Auvik Tab to Configuration Item Modal - [ ] 3.1 Create `/components/configuration-items/auvik-tab.tsx` component accepting `device?: AuvikDevice` prop - [ ] 3.2 Import required UI components (Card, CardContent, CardHeader, Badge, Label) and icons (Network, Info, Wifi, Shield) - [ ] 3.3 Implement empty state UI when no device provided (show "No Auvik data available" message with icon) - [ ] 3.4 Create "Basic Information" section displaying: device name, device type, serial number, manufacturer, model - [ ] 3.5 Create "Network Information" section displaying: IP addresses (list), MAC addresses (list), primary interface details - [ ] 3.6 Create "Status Information" section displaying: online/offline badge, last seen timestamp (formatted), uptime (formatted duration) - [ ] 3.7 Create "Firmware Information" section displaying: firmware version, last updated date - [ ] 3.8 Create "Network Interfaces" section displaying table/list of interfaces with name, status, speed, MAC address - [ ] 3.9 Style online status with green badge and Wifi icon, offline with gray badge and X icon - [ ] 3.10 Use consistent spacing and layout matching existing PSA/RMM tabs (2-column grid on desktop) - [ ] 3.11 Modify `/components/configuration-items/config-item-modal.tsx` to add Auvik tab to TabsList - [ ] 3.12 Add TabsTrigger for "Auvik Data" with Network icon and online/offline badge if device exists - [ ] 3.13 Add TabsContent for "auvik" value rendering AuvikTab component with auvikDevice prop - [ ] 3.14 Update modal state to include `auvikDevice?: AuvikDevice` in ConfigItemDetail interface - [ ] 4.0 Add Auvik Column to Configuration Items Table - [ ] 4.1 Open `/app/configuration-items/page.tsx` and locate the table header row (TableHead components) - [ ] 4.2 Add new `Auvik` column after the RMM column - [ ] 4.3 Update colspan values in grouped rows from current value to +1 (account for new column) - [ ] 4.4 In the table body, add new TableCell after RMM cell for grouped rows - [ ] 4.5 Display green CheckCircle icon if `item.auvikDevice` exists, gray XCircle if not - [ ] 4.6 Add same TableCell logic for non-grouped rows (around line 1060+) - [ ] 4.7 Update DeviceComparison interface to include `auvikDevice?: AuvikDevice` field - [ ] 4.8 Import AuvikDevice type from `/lib/types/auvik` - [ ] 5.0 Implement Device Matching Logic - [ ] 5.1 Modify `/app/api/rmm-devices/route.ts` to fetch Auvik devices at the start of GET handler - [ ] 5.2 Call `getAuvikClient().getAllDevices()` or `getDevicesByTenant()` if companyName provided - [ ] 5.3 Wrap Auvik API call in try-catch to handle failures gracefully (continue with empty array) - [ ] 5.4 Create helper function `matchAuvikDevice(autotaskDevice: ConfigurationItem, auvikDevices: AuvikDevice[]): AuvikDevice | null` - [ ] 5.5 Implement Priority 1 matching: Compare serial numbers (case-insensitive, trimmed) - [ ] 5.6 Implement Priority 2 matching: Compare hostnames using `rmmDeviceAuditHostname` or `referenceTitle` (case-insensitive) - [ ] 5.7 Implement Priority 3 matching: Compare MAC addresses (normalize format, check against all device MACs) - [ ] 5.8 Create `normalizeMacAddress()` helper function to strip colons/hyphens and lowercase - [ ] 5.9 In comparison loop, call matchAuvikDevice for each autotaskDevice and add result to comparison object - [ ] 5.10 Log matching results with match method (serial/hostname/MAC) for debugging - [ ] 5.11 Modify `/app/api/configuration-items/[id]/route.ts` GET handler to fetch Auvik devices - [ ] 5.12 Use same matchAuvikDevice logic to find matching device for the single configuration item - [ ] 5.13 Include auvikDevice in response JSON: `{ autotaskDevice, rmmDevice, auvikDevice, companyName }` - [ ] 5.14 Add console logging for Auvik device matching in detail endpoint - [ ] 6.0 Testing and Error Handling - [ ] 6.1 Test Auvik API authentication with valid credentials (verify 200 response) - [ ] 6.2 Test with invalid credentials (verify graceful failure, no app crash) - [ ] 6.3 Test device matching with serial number match (verify correct device returned) - [ ] 6.4 Test device matching with hostname match (verify fallback works) - [ ] 6.5 Test device matching with MAC address match (verify normalization works) - [ ] 6.6 Test device matching with no match (verify null returned, "-" displayed) - [ ] 6.7 Test with company that has no Auvik tenant (verify all devices returned or empty array) - [ ] 6.8 Test tenant name matching with exact match and fuzzy match scenarios - [ ] 6.9 Test configuration items page with Auvik API unavailable (verify page still loads) - [ ] 6.10 Test modal opening with Auvik device (verify tab displays data correctly) - [ ] 6.11 Test modal opening without Auvik device (verify empty state message) - [ ] 6.12 Test table column alignment with new Auvik column (verify no layout issues) - [ ] 6.13 Verify console logs show appropriate messages for matching, errors, and API calls - [ ] 6.14 Test with large device list (100+ devices) to verify performance - [ ] 6.15 Test responsive layout on mobile/tablet (verify Auvik tab and column display correctly) - [ ] 6.16 Verify TypeScript compilation with no errors - [ ] 6.17 Test that existing PSA and RMM functionality is not affected by changes