diff --git a/specs/002-product-list/tasks.md b/specs/002-product-list/tasks.md new file mode 100644 index 0000000..559cf37 --- /dev/null +++ b/specs/002-product-list/tasks.md @@ -0,0 +1,228 @@ +# Tasks: Product Selection Landing Page + +**Input**: Design documents from `/home/markus/workspace/reklamator/specs/002-product-list/` +**Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/landing-page.yaml + +**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story. + +## Format: `[ID] [P?] [Story] Description` +- **[P]**: Can run in parallel (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) +- Include exact file paths in descriptions + +## Path Conventions +- Web application structure: `app/`, `tests/` at repository root +- Following existing Flask structure from feature 001 + +--- + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: No new setup needed - feature reuses existing Flask infrastructure + +*This phase is empty - all infrastructure from feature 001 is reused* + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Core Product model extension needed by all user stories + +**⚠️ CRITICAL**: User Story 1 depends on this extension + +- [ ] T001 [US1] Extend Product model with load_active() class method in app/models/product.py + +**Checkpoint**: Product.load_active() method ready - User Story 1 implementation can begin + +--- + +## Phase 3: User Story 1 - Browse and Select Product (Priority: P1) 🎯 MVP + +**Goal**: Enable visitors to discover products via landing page at `/` and navigate to submission forms + +**Independent Test**: Visit `/`, see active products listed, click a product link, verify redirect to `/submit/{slug}` + +### Tests for User Story 1 (TDD - Write FIRST, ensure FAIL) + +- [ ] T002 [P] [US1] Contract test: GET / with active products returns 200 with product list HTML in tests/contract/test_landing_routes.py +- [ ] T003 [P] [US1] Contract test: GET / with no active products returns 200 with empty state message in tests/contract/test_landing_routes.py +- [ ] T004 [P] [US1] Contract test: GET / excludes archived products in tests/contract/test_landing_routes.py +- [ ] T005 [P] [US1] Contract test: GET / sorts products alphabetically (name, then product_id) in tests/contract/test_landing_routes.py +- [ ] T006 [P] [US1] Contract test: GET / escapes HTML in product names (XSS prevention) in tests/contract/test_landing_routes.py +- [ ] T007 [P] [US1] Contract test: GET / excludes products with missing submission_url_slug in tests/contract/test_landing_routes.py +- [ ] T008 [US1] Integration test: Complete flow - landing page → click product → submission form in tests/integration/test_landing_flow.py + +### Implementation for User Story 1 + +- [ ] T009 [US1] Create landing route blueprint in app/routes/landing.py +- [ ] T010 [US1] Register landing blueprint in app/__init__.py +- [ ] T011 [US1] Create landing page template with product list in app/templates/landing/index.html +- [ ] T012 [US1] Add logging for landing page access in app/routes/landing.py +- [ ] T013 [US1] Verify all tests pass for User Story 1 + +**Checkpoint**: User Story 1 complete and independently testable. MVP ready for demo/deploy. + +--- + +## Phase 4: User Story 2 - See Product Availability Status (Priority: P2) + +**Goal**: Ensure only active products are visible (archived products excluded) + +**Independent Test**: Create products with status 'active' and 'archived', verify only active products appear on landing page + +**Status**: This functionality is already implemented in User Story 1 via the Product.load_active() filtering logic. No additional tasks needed. + +**Verification**: Test T004 already validates this behavior. + +--- + +## Phase 5: User Story 3 - Direct Navigation with Known Product (Priority: P3) + +**Goal**: Maintain backwards compatibility - direct `/submit/{slug}` URLs continue to work + +**Independent Test**: Navigate directly to `/submit/{slug}`, verify submission form loads (no landing page interference) + +**Status**: This is backwards compatibility verification only. No new implementation needed - existing submission routes are unchanged. + +### Verification for User Story 3 + +- [ ] T014 [US3] Manual test: Verify direct URL `/submit/{slug}` still works without landing page interference +- [ ] T015 [US3] Manual test: Verify alphabetical sorting helps users find products efficiently on landing page + +**Checkpoint**: Backwards compatibility confirmed. All 3 user stories validated. + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +**Purpose**: Final validations and quality checks + +- [ ] T016 [P] Manual verification: Visit `/` with 0 active products - see empty state message +- [ ] T017 [P] Manual verification: Visit `/` with 1 active product - see single product listed +- [ ] T018 [P] Manual verification: Visit `/` with 10+ active products - verify alphabetical order +- [ ] T019 [P] Manual verification: Check product with no description - verify no placeholder text shown +- [ ] T020 [P] Manual verification: Check product with long name - verify proper text wrapping +- [ ] T021 [P] Manual verification: Access `/` as anonymous user - page accessible +- [ ] T022 [P] Manual verification: Access `/` as authenticated user - same page shown (no redirect) +- [ ] T023 [P] Manual verification: View page source - confirm no JavaScript present +- [ ] T024 [P] Performance verification: Load landing page with 100 products - confirm <1 second load time +- [ ] T025 Commit all changes with descriptive message + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: Empty - no setup needed +- **Foundational (Phase 2)**: T001 must complete before User Story 1 - BLOCKS US1 +- **User Story 1 (Phase 3)**: Depends on T001 completion - Core MVP +- **User Story 2 (Phase 4)**: Already implemented in US1 - No additional work +- **User Story 3 (Phase 5)**: Manual verification only - Depends on US1 +- **Polish (Phase 6)**: Depends on US1 completion + +### Task Dependencies + +**Foundational**: +- T001: No dependencies - can start immediately + +**User Story 1** (BLOCKS: T009-T013 depend on T001): +- T002-T008: Tests can all run in parallel [P] - write FIRST +- T009: Depends on T001 (needs Product.load_active method) +- T010: Depends on T009 (needs blueprint to register) +- T011: Can run parallel with T009 [P] conceptually, but blueprint needed for testing +- T012: Depends on T009 (logging in route handler) +- T013: Depends on T002-T012 (final validation) + +**User Story 3**: +- T014-T015: Can run in parallel [P] - manual tests + +**Polish**: +- T016-T024: Can all run in parallel [P] - independent manual checks +- T025: Depends on all previous tasks + +### Parallel Opportunities + +**Tests (Phase 3)**: Launch T002, T003, T004, T005, T006, T007 together (all in same file, different test functions) + +**Manual Verification (Phase 6)**: Launch T016-T024 together (independent checks) + +--- + +## Parallel Example: User Story 1 + +```bash +# Launch all contract tests together (write FIRST): +Task: "Contract test: GET / with active products in tests/contract/test_landing_routes.py" +Task: "Contract test: GET / with no products in tests/contract/test_landing_routes.py" +Task: "Contract test: GET / excludes archived in tests/contract/test_landing_routes.py" +Task: "Contract test: GET / sorts alphabetically in tests/contract/test_landing_routes.py" +Task: "Contract test: GET / XSS prevention in tests/contract/test_landing_routes.py" +Task: "Contract test: GET / excludes missing slug in tests/contract/test_landing_routes.py" + +# Then implement in sequence: +Task: "Create landing route blueprint in app/routes/landing.py" +Task: "Register blueprint in app/__init__.py" +Task: "Create template in app/templates/landing/index.html" +``` + +--- + +## Implementation Strategy + +### MVP First (User Story 1 Only) + +1. Complete T001: Extend Product model (Foundational) +2. Complete T002-T008: Write all tests, verify they FAIL +3. Complete T009-T012: Implement landing page +4. Complete T013: Verify all tests PASS +5. **STOP and VALIDATE**: User Story 1 is independently testable MVP +6. Ready for demo/deploy + +### Incremental Delivery + +1. **Foundation** (T001) → Product.load_active() ready +2. **User Story 1** (T002-T013) → Test independently → Deploy (MVP!) +3. **User Story 2** → Already complete (filtering in US1) +4. **User Story 3** (T014-T015) → Verify backwards compatibility +5. **Polish** (T016-T025) → Final quality checks + +### Single Developer Strategy + +Execute tasks in numeric order (T001 → T025): +- T001: Extend model +- T002-T008: Write tests (all should FAIL) +- T009-T012: Implement feature +- T013: Verify tests PASS +- T014-T015: Manual backwards compatibility checks +- T016-T024: Manual quality checks +- T025: Commit + +--- + +## Notes + +- **TDD Discipline** (Constitution Principle II): Tests T002-T008 MUST be written BEFORE T009-T012 implementation +- **[P] tasks**: Can run in parallel (different test functions or independent manual checks) +- **[US1/US2/US3] labels**: Map task to specific user story for traceability +- **File paths**: All paths use existing Flask structure from feature 001 +- **Simplicity**: Only 25 tasks total - feature reuses existing infrastructure +- **Independent Stories**: US1 is core MVP, US2 already satisfied by US1, US3 is verification only +- **Manual tests**: T014-T024 are manual verification tasks (quickstart.md has detailed checklist) + +--- + +## Task Count Summary + +- **Total Tasks**: 25 +- **Foundational**: 1 task (T001) +- **User Story 1**: 12 tasks (T002-T013) - 7 tests, 5 implementation +- **User Story 2**: 0 tasks (functionality in US1) +- **User Story 3**: 2 tasks (T014-T015) - manual verification +- **Polish**: 10 tasks (T016-T025) - 9 manual checks, 1 commit + +**Parallel Opportunities**: +- Tests: 7 tests can be written in parallel (T002-T007, T008) +- Manual verification: 9 checks can run in parallel (T016-T024) + +**MVP Scope**: Tasks T001-T013 deliver complete User Story 1 (core product selection feature)