9.2 KiB
Tasks: Global Policy Search
Feature: 001-global-policy-search
Branch: 001-global-policy-search
Prerequisites: plan.md, spec.md, data-model.md, contracts/
Format: - [ ] [ID] [P?] [Story?] Description with file path
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (US1, US2, US3)
Phase 1: Setup (Shared Infrastructure)
Purpose: Project initialization and environment setup
- T001 Add POLICY_API_SECRET to .env file with secure random value (use openssl rand -base64 32)
- T002 Add POLICY_API_SECRET to lib/env.mjs as optional string validation
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
- T003 Create PolicySetting Drizzle schema in lib/db/schema/policySettings.ts
- T004 Export policySettings from lib/db/schema/index.ts (if exists) or lib/db/index.ts
- T005 Run npm run db:push to create policy_settings table
- T006 [P] Create Zod validators in lib/validators/policySettings.ts (policySettingSchema, bulkPolicySettingsSchema)
- T007 [P] Extend NextAuth session to include tenantId from Azure AD tid claim in lib/auth/utils.ts
- T008 Add POLICY_TYPES constant array to lib/db/schema/policySettings.ts
Checkpoint: Foundation ready - user story implementation can now begin in parallel
Phase 3: User Story 1 - Search Policy Settings (Priority: P1) 🎯 MVP
Goal: Enable admins to search for policy settings by keyword (e.g., "USB", "Camera") across their tenant's policies
Independent Test: Insert test data for a tenant, login as that tenant's user, search for a keyword, verify results show only that tenant's matching policies
Implementation for User Story 1
- T009 [P] [US1] Create searchPolicySettings Server Action in lib/actions/policySettings.ts
- T010 [P] [US1] Create getPolicySettingById Server Action in lib/actions/policySettings.ts
- T011 [P] [US1] Create getRecentPolicySettings Server Action in lib/actions/policySettings.ts
- T012 [US1] Create search page at app/(app)/search/page.tsx with search input and results table
- T013 [P] [US1] Create SearchInput component in components/search/SearchInput.tsx with debounce
- T014 [P] [US1] Create ResultsTable component in components/search/ResultsTable.tsx with columns: Setting Name, Setting Value, Policy Name, Policy Type
- T015 [P] [US1] Create EmptyState component in components/search/EmptyState.tsx for no results
- T016 [US1] Add search route to config/nav.ts with Search icon
Checkpoint: User Story 1 complete - Admins can search their tenant's policy settings independently
Phase 4: User Story 2 - Tenant-Isolated Results (Priority: P1)
Goal: Ensure admins ONLY see policy settings from their own tenant, never data from other customers
Independent Test: Create test data for two different tenants, login as tenant A, verify search only returns tenant A's data, verify tenant B's data is never visible
Implementation for User Story 2
Note: This user story is implemented through security measures in User Story 1 tasks. The tenant isolation logic is baked into:
- T007: Session with tenantId extraction
- T009: Server Actions filter by tenantId
- T012: Search page uses tenant-filtered actions
Additional Security Validation:
- T017 [US2] Add explicit tenantId WHERE clause to ALL database queries in lib/actions/policySettings.ts
- T018 [US2] Add security tests: verify getUserAuth returns tenantId, verify queries include tenantId filter
- T019 [US2] Add error handling for missing tenantId in session (return Unauthorized error)
Checkpoint: User Stories 1 AND 2 complete - Search works AND is fully tenant-isolated
Phase 5: User Story 3 - Data Ingestion API (Priority: P2)
Goal: Enable n8n workflows to ingest policy settings via API so search data stays up-to-date
Independent Test: Send POST request with policy data to /api/policy-settings with valid API_SECRET, verify data appears in database and is searchable
Implementation for User Story 3
- T020 [US3] Create POST handler in app/api/policy-settings/route.ts with X-API-SECRET validation
- T021 [US3] Implement bulk upsert logic using db.insert().onConflictDoUpdate() in app/api/policy-settings/route.ts
- T022 [US3] Add request body validation using bulkPolicySettingsSchema in app/api/policy-settings/route.ts
- T023 [US3] Add error responses: 401 for invalid secret, 400 for validation errors, 500 for DB errors
- T024 [P] [US3] Create DELETE handler in app/api/policy-settings/route.ts for tenant cleanup (query param: tenantId)
- T025 [US3] Test API endpoint with curl: POST with valid secret should return 200, POST without secret should return 401
Checkpoint: All user stories complete - Search works, is tenant-isolated, AND can ingest data from n8n
Phase 6: Polish & Cross-Cutting Concerns
Purpose: Improvements that affect multiple user stories
- T026 [P] Add loading states with Suspense boundaries to app/(app)/search/page.tsx
- T027 [P] Add toast notifications for search errors using Shadcn Sonner
- T028 Add rate limiting to API route (optional: check if needed for production)
- T029 Run through quickstart.md validation steps to verify complete setup
- T030 [P] Add JSDoc comments to all Server Actions in lib/actions/policySettings.ts
- T031 Test edge cases: empty search, very long search terms (>200 chars), special characters, SQL injection attempts
Dependencies & Execution Order
Phase Dependencies
Phase 1 (Setup)
↓
Phase 2 (Foundational) ← BLOCKS all user stories
↓
├─→ Phase 3 (US1 - Search) ← MVP: Can deploy after this
├─→ Phase 4 (US2 - Tenant Isolation) ← Implemented within US1
└─→ Phase 5 (US3 - Ingestion API)
↓
Phase 6 (Polish)
User Story Dependencies
- US1 (Search): Depends on Foundational phase (T003-T008) - No dependencies on other stories
- US2 (Tenant Isolation): Security measures integrated into US1 - Implemented through T007, T009, T012, plus additional validation T017-T019
- US3 (Ingestion API): Depends on Foundational phase (T003-T008) - Independent from US1/US2 (different files/endpoints)
Within Each Phase
Phase 2 (Foundational):
T001-T002 (Environment)
↓
T003 (Schema) → T004 (Export) → T005 (Migration)
↓
T006 (Validators) [P] ← Can run parallel with T007-T008
T007 (Auth Session) [P] ← Can run parallel with T006
T008 (Constants) [P] ← Can run parallel with T006-T007
Phase 3 (US1):
After Foundational:
T009-T011 (Server Actions) [P] ← All can run in parallel (different functions)
↓
T012 (Search Page) ← Needs T009-T011
T013-T015 (Components) [P] ← All can run in parallel (different files)
↓
T016 (Navigation) ← Needs T012
Phase 5 (US3):
After Foundational:
T020-T024 (API Route) ← Sequential in same file
↓
T025 (Testing)
Parallel Opportunities
- Setup Phase: T001 and T002 can run in parallel
- Foundational Phase: T006, T007, T008 can all run in parallel after T005
- US1 Phase: T009-T011 can run in parallel, then T013-T015 can run in parallel
- US3 and US1: Can be worked on by different developers in parallel (different files)
- Polish Phase: T026, T027, T030 can all run in parallel
Parallel Example: Starting Multiple User Stories
If you have multiple developers, after Phase 2 completes:
# Developer 1: User Story 1 (Search UI)
git checkout -b US1-search-ui
# Work on T009-T016
# Developer 2: User Story 3 (Ingestion API)
git checkout -b US3-ingestion-api
# Work on T020-T025
# Both can work independently and merge when complete
Suggested MVP Scope (Minimum Viable Product)
For fastest time-to-value, implement in this order:
- Phase 1 + Phase 2: Setup and Foundation (T001-T008) - ~2 hours
- Phase 3 (US1): Search functionality (T009-T016) - ~3 hours
- Phase 4 (US2): Security validation (T017-T019) - ~1 hour
Total MVP: ~6 hours of focused work
Result: Working search with full tenant isolation. Data can be added manually to DB for testing.
Later: Add Phase 5 (US3) for n8n ingestion when ready to automate data collection.
Implementation Strategy
- MVP First: Complete Phases 1-4 (Setup, Foundation, US1, US2) for immediate value
- Incremental Delivery: Each user story is independently testable and deployable
- Parallel Work: US1 and US3 can be developed simultaneously by different team members
- Test As You Go: Verify each checkpoint before proceeding to next phase
Task Count Summary
- Setup: 2 tasks
- Foundational: 6 tasks (blocking)
- User Story 1: 8 tasks
- User Story 2: 3 tasks (security validation)
- User Story 3: 6 tasks
- Polish: 6 tasks
Total: 31 tasks
Parallel Opportunities: 12 tasks can run in parallel (marked with [P])
Independent Test Criteria:
- US1: Search returns results, filtered by tenant
- US2: Tenant A cannot see Tenant B's data
- US3: POST to API with secret writes data to DB