tenantpilot/specs/001-global-policy-search/tasks.md
2025-12-05 22:06:22 +01:00

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:

  1. Phase 1 + Phase 2: Setup and Foundation (T001-T008) - ~2 hours
  2. Phase 3 (US1): Search functionality (T009-T016) - ~3 hours
  3. 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

  1. MVP First: Complete Phases 1-4 (Setup, Foundation, US1, US2) for immediate value
  2. Incremental Delivery: Each user story is independently testable and deployable
  3. Parallel Work: US1 and US3 can be developed simultaneously by different team members
  4. 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