tenantpilot/specs/002-manual-policy-sync/tasks.md
Ahmed Darrazi bd7758191e
All checks were successful
Trigger Cloudarix Deploy / call-webhook (push) Successful in 1s
Switch to development branch and update deployment workflow
2025-12-06 20:42:10 +01:00

319 lines
11 KiB
Markdown

---
description: "Task list for Manual Policy Sync Button feature"
---
# Tasks: Manual Policy Sync Button
**Branch**: `002-manual-policy-sync`
**Input**: [plan.md](./plan.md), [spec.md](./spec.md)
**Status**: ✅ **COMPLETED** (Documenting for record)
**Tests**: No test tasks included - manual testing only for this feature (as specified in plan.md)
**Organization**: Tasks organized by user story to enable independent implementation and testing
## Format: `- [ ] [ID] [P?] [Story] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (US1, US2, US3)
- Paths are absolute from repository root
---
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Configure environment and prepare existing codebase
- [x] T001 Add N8N_SYNC_WEBHOOK_URL to lib/env.mjs server schema with z.string().optional()
- [x] T002 [P] Verify existing authentication extracts tenantId in lib/auth/utils.ts
- [x] T003 [P] Confirm Shadcn Button and Toast (sonner) are available
**Status**: ✅ Complete - No new project setup needed, leveraging existing infrastructure
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
- [x] T004 Verify NextAuth session includes tenantId field (already implemented in previous feature)
- [x] T005 Verify getUserAuth() server action exists in lib/auth/utils.ts
- [x] T006 Confirm fetch() is available for webhook calls (Node.js built-in)
**Status**: ✅ Complete - All foundational pieces already exist from 001-global-policy-search feature
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
---
## Phase 3: User Story 1 - Trigger Immediate Sync (Priority: P1) 🎯 MVP
**Goal**: Admin can click button to trigger n8n webhook for immediate policy sync
**Independent Test**: Login → /search page → Click "Sync Policies" → Success toast appears → n8n receives POST with tenantId
### Implementation for User Story 1
- [x] T007 [P] [US1] Create SyncButton component in components/search/SyncButton.tsx
- [x] T008 [P] [US1] Implement triggerPolicySync() Server Action in lib/actions/policySettings.ts
- [x] T009 [US1] Add authentication check with getUserAuth() in triggerPolicySync()
- [x] T010 [US1] Extract tenantId from session with null check
- [x] T011 [US1] Validate N8N_SYNC_WEBHOOK_URL environment variable exists
- [x] T012 [US1] Implement fetch POST request to webhook with JSON body
- [x] T013 [US1] Add useTransition() hook in SyncButton for loading state
- [x] T014 [US1] Implement handleSync function calling Server Action
- [x] T015 [US1] Add success toast notification "Policy sync triggered successfully"
- [x] T016 [US1] Render Button with RefreshCw icon from lucide-react
- [x] T017 [US1] Integrate SyncButton into app/(app)/search/page.tsx CardHeader
- [x] T018 [US1] Position button right of title using flexbox (justify-between)
**Files Modified**:
-`lib/env.mjs` - Added N8N_SYNC_WEBHOOK_URL
-`lib/actions/policySettings.ts` - Added triggerPolicySync() function
-`components/search/SyncButton.tsx` - Created new component
-`app/(app)/search/page.tsx` - Integrated SyncButton
**Checkpoint**: ✅ User Story 1 is fully functional and testable independently
---
## Phase 4: User Story 2 - Handle Sync Errors Gracefully (Priority: P2)
**Goal**: Admin receives clear error feedback when sync fails
**Independent Test**: Simulate webhook failure (wrong URL, network error) → Error toast appears with user-friendly message
### Implementation for User Story 2
- [x] T019 [US2] Add try-catch block in triggerPolicySync() to handle network errors
- [x] T020 [US2] Return error response when session.user is null ("Not authenticated")
- [x] T021 [US2] Return error response when tenantId is null ("No tenant ID found in session")
- [x] T022 [US2] Return error response when N8N_SYNC_WEBHOOK_URL is not configured ("Sync webhook not configured")
- [x] T023 [US2] Check webhook response status and throw error if not ok
- [x] T024 [US2] Add error toast notification in SyncButton handleSync catch block
- [x] T025 [US2] Add console.error logging in triggerPolicySync() for debugging
- [x] T026 [US2] Ensure button returns to normal state after error (useTransition handles this)
**Files Modified**:
-`lib/actions/policySettings.ts` - Added comprehensive error handling
-`components/search/SyncButton.tsx` - Added error toast display
**Checkpoint**: ✅ User Stories 1 AND 2 both work independently with proper error handling
---
## Phase 5: User Story 3 - Prevent Multiple Simultaneous Syncs (Priority: P3)
**Goal**: Button prevents duplicate requests during sync operation
**Independent Test**: Click button rapidly multiple times → Only one request sent, button stays disabled
### Implementation for User Story 3
- [x] T027 [US3] Add disabled prop to Button based on isPending state
- [x] T028 [US3] Conditionally render "Syncing..." text when isPending is true
- [x] T029 [US3] Add animate-spin class to RefreshCw icon when isPending is true
- [x] T030 [US3] Verify useTransition() prevents multiple simultaneous calls
**Files Modified**:
-`components/search/SyncButton.tsx` - Added disabled state and loading UI
**Checkpoint**: ✅ All user stories (1, 2, 3) are independently functional with proper UX
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Final touches and production readiness
- [x] T031 Test button on mobile responsive layout
- [x] T032 Verify button styling matches existing search page design
- [x] T033 Test with missing N8N_SYNC_WEBHOOK_URL → Error toast appears
- [x] T034 Test with unauthenticated user → Error toast appears
- [x] T035 Test with mock webhook success → Success toast appears
- [x] T036 Document N8N_SYNC_WEBHOOK_URL in deployment notes
- [x] T037 Commit changes to 002-manual-policy-sync branch
- [x] T038 Create specification and plan documentation
**Status**: ✅ Complete - All polish tasks finished
---
## Deployment Checklist
- [x] All tasks completed (T001-T038)
- [x] Code committed to feature branch
- [x] Specification (spec.md) created
- [x] Implementation plan (plan.md) created
- [x] Tasks (tasks.md) documented
- [ ] **TODO**: Configure N8N_SYNC_WEBHOOK_URL in Dokploy environment variables
- [ ] **TODO**: Merge 002-manual-policy-sync → main
- [ ] **TODO**: Deploy to production
- [ ] **TODO**: Verify button appears on /search page in production
- [ ] **TODO**: Test manual sync trigger with real n8n webhook
---
## Dependencies Between Tasks
**Legend**: `→` means "depends on"
```text
Setup Phase:
T001, T002, T003 → [Can run in parallel]
Foundational Phase:
T004, T005, T006 → [Already complete from previous work]
User Story 1 (Core Sync):
T007 [SyncButton UI] → T013-T018 [UI refinements]
T008 [Server Action] → T009-T012 [Action logic]
T007, T008 → T017 [Page integration]
User Story 2 (Error Handling):
T008 complete → T019-T025 [Add error cases]
T007 complete → T024, T026 [Error UI feedback]
User Story 3 (Prevent Duplicates):
T007, T013 complete → T027-T030 [Loading state enhancements]
```
**Parallel Opportunities**:
- Phase 1: All tasks (T001-T003) can run in parallel
- User Story 1: T007 (UI) and T008 (Server Action) can be built in parallel
- User Story 2: Error handling can be added to both files simultaneously
---
## Parallel Execution Examples
### Example 1: User Story 1 (Two Developers)
**Developer A** (Frontend):
```bash
# Create SyncButton component
- T007: components/search/SyncButton.tsx (stub Server Action call)
- T013-T016: Add loading state, toast, button rendering
- T017-T018: Integrate into search page
```
**Developer B** (Backend):
```bash
# Create Server Action
- T008: lib/actions/policySettings.ts (stub return success)
- T009-T012: Add auth check, tenant ID extraction, webhook call
```
**Integration**: Once both T007 and T008 are complete, connect them together
### Example 2: User Story 2 (One Developer)
```bash
# Add error handling after US1 is complete
- T019-T023: Server Action error cases (5 min each)
- T024-T026: UI error handling (5 min each)
- Total time: ~30 minutes
```
---
## Implementation Strategy
### MVP-First Approach
**MVP = User Story 1 ONLY (P1)**:
- Admin can click button
- Button shows loading state
- Success toast appears
- n8n receives webhook
This delivers immediate value and can be shipped independently.
### Incremental Delivery
**Release 1**: User Story 1 (P1) - Core sync functionality
**Release 2**: Add User Story 2 (P2) - Error handling
**Release 3**: Add User Story 3 (P3) - UX polish
Each release is independently valuable and deployable.
---
## Testing Notes
**Manual Testing Checklist** (from plan.md):
**Happy Path**:
- [x] Login → /search → Click "Sync Policies" → Loading state → Success toast
- [x] Verify n8n receives POST with correct tenantId
**Error Cases**:
- [x] Not authenticated → Error toast
- [x] No tenantId in session → Error toast
- [x] Webhook URL not configured → Error toast
- [x] Network error → Error toast
- [x] Webhook returns 500 → Error toast
**UI/UX**:
- [x] Button shows spinner during sync
- [x] Button disabled during sync
- [x] Rapid clicks don't send duplicates
- [x] Mobile responsive
**No automated tests for this feature** - manual testing deemed sufficient for MVP (as per plan.md).
---
## Task Summary
**Total Tasks**: 38
**Completed**: 38 ✅
**Remaining**: 0
**Tasks by User Story**:
- Setup: 3 tasks
- Foundational: 3 tasks
- User Story 1 (P1): 12 tasks
- User Story 2 (P2): 8 tasks
- User Story 3 (P3): 4 tasks
- Polish: 8 tasks
**Parallel Opportunities**: 15 tasks marked [P] can run in parallel
**Critical Path**: Setup → Foundational → US1 core (T007-T012) → US2 errors → US3 UX → Polish
**Estimated Implementation Time** (if starting from scratch):
- Setup: 15 minutes
- Foundational: 0 minutes (already done)
- User Story 1: 2 hours
- User Story 2: 30 minutes
- User Story 3: 20 minutes
- Polish: 30 minutes
- **Total**: ~3.5 hours
**Actual Time**: Already completed ✅
---
## Next Feature Recommendations
Based on this implementation, consider these follow-up features:
1. **Sync History Tracking** (new spec)
- Track when syncs were triggered
- Display last sync timestamp on search page
- Show sync status (pending, success, failed)
2. **Rate Limiting** (enhancement to 002)
- Prevent syncs more frequently than once per 5 minutes
- Show countdown timer until next sync allowed
3. **Bulk Tenant Sync** (admin feature)
- Allow platform admins to trigger sync for all tenants
- New admin dashboard page
- Requires admin role system
These can each be separate feature specs following the same workflow.