# Feature Specification: Manual Policy Sync Button **Feature Branch**: `002-manual-policy-sync` **Created**: 2025-12-06 **Status**: Draft **Input**: User description: "Manual Policy Sync Button - Allow admins to trigger immediate policy synchronization from Intune without waiting for scheduled sync" ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Trigger Immediate Sync (Priority: P1) An IT administrator has just made changes to an Intune policy and wants to see those changes reflected in TenantPilot immediately without waiting for the scheduled nightly sync. **Why this priority**: Core functionality that directly addresses the pain point of waiting for scheduled syncs. Delivers immediate value and is the primary reason for this feature. **Independent Test**: Admin can click "Sync Policies" button on search page, receives confirmation that sync started, and n8n workflow is triggered for their tenant. **Acceptance Scenarios**: 1. **Given** an authenticated admin is on the `/search` page, **When** they click the "Sync Policies" button, **Then** the button shows a loading state with "Syncing..." text and a spinner 2. **Given** a sync request is successfully sent to n8n, **When** the request completes, **Then** a success toast message appears saying "Policy sync triggered successfully" 3. **Given** an authenticated admin with a valid tenant ID, **When** they trigger a sync, **Then** the n8n webhook receives a POST request with their tenant ID and source "manual_trigger" --- ### User Story 2 - Handle Sync Errors Gracefully (Priority: P2) When the sync cannot be triggered (network error, webhook down, etc.), the admin needs clear feedback about what went wrong. **Why this priority**: Essential for production reliability. Without error handling, users won't know if sync failed and may think it succeeded. **Independent Test**: Can be tested by simulating webhook failures (wrong URL, network timeout) and verifying error messages appear. **Acceptance Scenarios**: 1. **Given** the n8n webhook is unreachable, **When** admin clicks "Sync Policies", **Then** an error toast appears with message "Failed to trigger sync. Please try again later." 2. **Given** a sync request fails, **When** the error occurs, **Then** the button returns to its normal state (not stuck in loading) 3. **Given** user is not authenticated, **When** they attempt to trigger sync, **Then** they receive "Not authenticated" error --- ### User Story 3 - Prevent Multiple Simultaneous Syncs (Priority: P3) Admin should not be able to trigger multiple syncs simultaneously for the same tenant to avoid duplicate processing. **Why this priority**: Nice-to-have for UX polish. Prevents confusion but not critical for MVP since n8n workflows can handle duplicates. **Independent Test**: Click sync button multiple times rapidly and verify only one request is sent, button stays disabled during processing. **Acceptance Scenarios**: 1. **Given** a sync is in progress, **When** admin clicks the button again, **Then** the button remains disabled and no additional request is sent 2. **Given** a sync completes (success or error), **When** the toast dismisses, **Then** the button becomes clickable again --- ### Edge Cases - What happens when user's session has no tenant ID? (Show error: "No tenant ID found in session") - What happens when N8N_SYNC_WEBHOOK_URL environment variable is not configured? (Show error: "Sync webhook not configured") - What happens when n8n webhook returns non-200 status? (Log error, show user-friendly message) - What happens if user navigates away while sync is in progress? (No issue - webhook call already sent, no cleanup needed) ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: System MUST provide a "Sync Policies" button on the `/search` page visible to authenticated users - **FR-002**: System MUST validate user authentication before allowing sync trigger - **FR-003**: System MUST extract tenant ID from user session and include it in webhook payload - **FR-004**: System MUST send POST request to n8n webhook with JSON body containing `{ tenantId, source: "manual_trigger", triggeredAt: ISO timestamp }` - **FR-005**: System MUST show loading state (spinner + "Syncing..." text) while request is in progress - **FR-006**: System MUST display success toast notification when sync is triggered successfully - **FR-007**: System MUST display error toast notification when sync fails with user-friendly error message - **FR-008**: System MUST disable button during sync operation to prevent duplicate requests - **FR-009**: System MUST log sync errors to console for debugging - **FR-010**: System MUST validate that N8N_SYNC_WEBHOOK_URL environment variable is configured before attempting request ### Key Entities *(include if feature involves data)* - **Sync Request**: Represents a manual sync trigger event - Attributes: tenantId (from session), source ("manual_trigger"), triggeredAt (ISO timestamp) - Sent to n8n webhook, not persisted in database - Used for audit trail in n8n workflow logs ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: Admin can trigger policy sync with single button click from search page - **SC-002**: Sync request reaches n8n webhook within 2 seconds of button click - **SC-003**: Admin receives visual feedback (loading state + toast) within 1 second of clicking button - **SC-004**: Error scenarios (network failure, missing config) show clear error messages to user - **SC-005**: Button correctly handles rapid multiple clicks without sending duplicate requests - **SC-006**: 100% of sync triggers include correct tenant ID from authenticated user's session ## Assumptions - N8N_SYNC_WEBHOOK_URL will be configured in environment variables before feature deployment - n8n workflow already exists and can handle manual sync requests (separate from scheduled sync) - Webhook endpoint accepts POST requests with JSON body - Tenant ID is always available in authenticated user's session (handled by existing auth logic) - No database changes required - this is a client-side UI + server action feature - Sync is asynchronous - user doesn't wait for actual Intune data fetch to complete ## Dependencies - Existing authentication system (NextAuth with tenant ID in session) - Existing server actions infrastructure (`lib/actions/policySettings.ts`) - Existing UI components (Shadcn Button, Toast from sonner) - n8n webhook endpoint must be deployed and accessible - Environment variable validation system (`lib/env.mjs`) ## Out of Scope - Showing sync progress or status (user only gets confirmation that sync was triggered) - Displaying last sync timestamp on the page - Limiting sync frequency (e.g., rate limiting to once per 5 minutes) - Syncing specific policies (all policies for tenant are synced) - Admin controls for other tenants (admin can only sync their own tenant)